home *** CD-ROM | disk | FTP | other *** search
- PAGE 59, 132
-
- TITLE MSYIBM -- Module to perform VT100 emulation on IBM PC
-
- ; Update 7 Jan 86
-
- IF1
- %OUT >> Starting pass 1
- ELSE
- %OUT >> Starting pass 2
- ENDIF
-
- PUBLIC Term_PC, Gss, Close_Screen_PC, Get_Screen_Segment, Check_Table
- PUBLIC Set_up_script_processor_PC, Screen_Image_ptr, Mode_Line_ptr
- PUBLIC Old_Image, Set_up_dynamic_memory
- PUBLIC Save_command_mode_screen, Restore_command_mode_screen
-
- .SALL
-
- ;***************************************************************************
-
- ; *Definitions* ...
-
- ; Global defs
-
- INCLUDE MsDefs.H
-
- ; Local defs
-
- Screen EQU 10h ; BIOS screen call
- Kb EQU 16h ; BIOS keyboard call
-
- PrScan EQU 72h ; print-screen scan code...
-
- Caps_State EQU 40h ; CAPS LOCK on
- Num_State EQU 20h ; NUM LOCK on
-
- alt_shift EQU 8H ; alt shift key down
- ctl_shift EQU 4H ; ctl key down
- left_shift EQU 2H ; left shift key down
- right_shift EQU 1H ; right shift key down
-
- timer EQU 40h ; timer port
- bel_prt EQU 61h ; speaker control
-
- CRT_status_port EQU 3DAh ; Crt status port
- Vertical_retrace EQU 8 ; Vertical retrace in progress
-
- ;***************************************************************************
-
- ; *Data* ...
-
- DataS SEGMENT public 'datas'
-
- EXTRN PC_Subtype:BYTE, Force_mono:BYTE, m7171:BYTE, AutoWrap:BYTE
- EXTRN Preload_flag:BYTE, Preload_buffer:BYTE, PC_Type:BYTE
- EXTRN Video_page_addresses:WORD, Which_page:BYTE, CRT_Mode:BYTE
- EXTRN Count:WORD, Allow_blast:BYTE
-
- ; Fixed data, unchanging ...
-
- ; Character decoding dispatch tables ...
-
- ; Dispatch for single characters ...
-
- ChrTb1 DB Bell, Bs, Tab
- DB Lf, Ff, Cr
- DB Vt, ShO, ShI
- NChrTb1 EQU $-ChrTb1
- ActTb1 DW Do_Bell, Do_Bs, Do_Tab
- DW IND, IND, Do_Cr
- DW IND, Do_SO, Do_SI
- DW Done_with_char
-
- ; Dispatch for things following an escape ...
-
- ChrTb2 DB '[', '(', ')'
- DB '#', 'D', 'E'
- DB 'M', 'Z', '7'
- DB '8', '=', '>'
- DB Esc
- NChrTb2 EQU $-ChrTb2
- ActTb2 DW Do_left_square, Do_left_paren, Do_right_paren
- DW Do_pound_sign, IND, NEL
- DW RI, DECID, DECSC
- DW DECRC, DECKPAM, DECKPNM
- DW Restart_esc_seq_processing
- DW Done_with_char
-
- ; Dispatch for things following escape [ ...
-
- ChrTb3 DB 'A', 'B', 'C'
- DB 'D', 'H', 'J'
- DB 'K', 'c', 'f'
- DB 'h', 'i', 'l'
- DB 'm', 'n', 'q'
- DB 'r', Esc
- NChrTb3 EQU $-ChrTb3
- ActTb3 DW CUU, CUD, CUF
- DW CUB, CUP, ED
- DW EL, DA, HVP
- DW SM, MC, RM
- DW SGR, DSR, DECLL
- DW DECSTBM, Restart_esc_seq_processing
- DW Done_with_char
-
- ; Dispatch for things following escape ( ...
-
- ChrTb4 DB 'B', '0', Esc
- NChrTb4 EQU $-ChrTb4
- ActTb4 DW Lfp_B, Lfp_0, Restart_esc_seq_processing
- DW Done_with_char
-
- ; Dispatch for things following escape ) ...
-
- ChrTb5 DB 'B', '0', Esc
- NChrTb5 EQU $-ChrTb5
- ActTb5 DW Rtp_B, Rtp_0, Restart_esc_seq_processing
- DW Done_with_char
-
-
- EVEN ; Try for word boundary
-
- ; Lookup tables to convert renditions into attribute bytes
-
- Color_attributes LABEL BYTE
- DB 007h ; * Normal *
- DB 00Fh ; Bold
- DB 001h ; Underscored
- DB 009h ; Bold Underscored
- DB 087h ; Blinking
- DB 08Fh ; Bold Blinking
- DB 081h ; Underscored Blinking
- DB 089h ; Bold Underscored Blinking
- DB 070h ; Inverted
- DB 078h ; Bold Inverted
- DB 071h ; Underscored Inverted
- DB 079h ; Bold Underscored Inverted
- DB 0F0h ; Blinking Inverted
- DB 0F8h ; Bold Blinking Inverted
- DB 0F1h ; Underscored Blinking Inverted
- DB 0F9h ; Bold Underscored Blinking Inverted
-
-
- ; Mode change table, used for switching video modes
-
- Mode_change_table LABEL BYTE
- DB 2 ; 0 => 2
- DB 3 ; 1 => 3
- DB 2 ; 2 => 2
- DB 3 ; 3 => 3
- DB 3 ; 4 => 3
- DB 2 ; 5 => 2
- DB 2 ; 6 => 2
- DB 7 ; 7 => 7
- DB 8 ; 8 => 8
- DB 9 ; 9 => 9
- DB 0Ah ; A => A
- DB 0Bh ; B => B
- DB 0Ch ; C => C
- DB 3 ; D => 3
- DB 3 ; E => 3
- DB 2 ; F => 2
- DB 3 ; 10 => 3
-
-
- ; Dispatch table for Load LEDs (DECLL) routine
-
- DECLL_Table LABEL WORD
- DW DECLL_0 ; 0 -- Clear all LEDs
- DW DECLL_1 ; 1 -- Set LED #1
- DW DECLL_2 ; 2 -- Set LED #2
- DW DECLL_3 ; 3 -- Set LED #3
- DW DECLL_4 ; 4 -- Set LED #4
-
-
- ; Dispatch table for Erase in Display (ED) routine
-
- ED_table LABEL WORD
- DW ED_0 ; 0 -- Clear to end of screen
- DW ED_1 ; 1 -- Clear to beginning of screen
- DW ED_2 ; 2 -- Clear entire screen
-
-
- ; Dispatch table for Erase in Line (EL) routine
-
- EL_table LABEL WORD
- DW EL_0 ; 0 -- Clear to end of line
- DW EL_1 ; 1 -- Clear to beginning of line
- DW EL_2 ; 2 -- Clear entire line
-
-
- ; Dispatch table for Set Graphic Rendition (SGR) routine
-
- SGR_Table LABEL WORD
- DW SGR_0 ; 0 -- Clear all renditions
- DW SGR_1 ; 1 -- Bold
- DW SGR_Ignore ; 2
- DW SGR_Ignore ; 3
- DW SGR_4 ; 4 -- Underscored
- DW SGR_5 ; 5 -- Blinking
- DW SGR_Ignore ; 6
- DW SGR_7 ; 7 -- Inverted
-
-
- ; Dispatch table for Media Copy (MC) routine
-
- MC_Table LABEL WORD
- DW MC_0 ; 0 -- Print screen
- DW MC_1 ; 1 -- Print cursor line
- DW MC_Ignore ; 2
- DW MC_Ignore ; 3
- DW MC_4 ; 4 -- Printer controller or Auto Print off
- DW MC_5 ; 5 -- Printer controller or Auto Print on
-
-
- ; Strings to be sent for simulated VT100 keys
-
- PF1_str DB Esc,'OP',0
- PF2_str DB Esc,'OQ',0
- PF3_str DB Esc,'OR',0
- PF4_str DB Esc,'OS',0
-
- ; If cursor keys mode is not set ...
-
- Normal_PF7_str DB Esc,'[A',0
- Normal_PF8_str DB Esc,'[B',0
- Normal_PF9_str DB Esc,'[D',0
- Normal_PF10_str DB Esc,'[C',0
-
- ; If cursor keys mode is set ...
-
- Alternate_PF7_str DB Esc,'OA',0
- Alternate_PF8_str DB Esc,'OB',0
- Alternate_PF9_str DB Esc,'OD',0
- Alternate_PF10_str DB Esc,'OC',0
-
- ; As above, but in 7171 mode ...
-
- K71_PF1_str DB Esc,'1',0
- K71_PF2_str DB Esc,'2',0
- K71_PF3_str DB Esc,'3',0
- K71_PF4_str DB Esc,'4',0
- K71_PF5_str DB Esc,'5',0
- K71_PF6_str DB Esc,'6',0
- K71_PF7_str DB Esc,'7',0
- K71_PF8_str DB Esc,'8',0
- K71_PF9_str DB Esc,'9',0
- K71_PF10_str DB Esc,'0',0
- K71_PF11_str DB Esc,'-',0
- K71_PF12_str DB Esc,'=',0
- K71_Erase_EOL_str DB Esc,127,0
- K71_Home_str DB 8,0
- K71_Tab_str DB Esc,Esc,'OC',0
- K71_Shift_Tab_str DB Esc,Esc,'OD',0
- K71_End_str DB 'J'-100q,0
- K71_Del_str DB 127,0
- K71_Ins_str DB Esc,'On',0
- Null_string DB 0 ; String with no characters
-
- ; If keypad application mode is not set ...
-
- Num_Zero_str DB '0',0
- Num_One_str DB '1',0
- Num_Two_str DB '2',0
- Num_Three_str DB '3',0
- Num_Four_str DB '4',0
- Num_Five_str DB '5',0
- Num_Six_str DB '6',0
- Num_Seven_str DB '7',0
- Num_Eight_str DB '8',0
- Num_Nine_str DB '9',0
- Num_Period_str DB '.',0
- Num_Comma_str DB ',',0
- Num_Minus_str DB '-',0
- Num_Enter_str DB Cr,0
-
- ; If keypad application mode is set ...
-
- Appl_Zero_str DB Esc,'Op',0
- Appl_One_str DB Esc,'Oq',0
- Appl_Two_str DB Esc,'Or',0
- Appl_Three_str DB Esc,'Os',0
- Appl_Four_str DB Esc,'Ot',0
- Appl_Five_str DB Esc,'Ou',0
- Appl_Six_str DB Esc,'Ov',0
- Appl_Seven_str DB Esc,'Ow',0
- Appl_Eight_str DB Esc,'Ox',0
- Appl_Nine_str DB Esc,'Oy',0
- Appl_Period_str DB Esc,'On',0
- Appl_Comma_str DB Esc,'Ol',0
- Appl_Minus_str DB Esc,'Om',0
- Appl_Enter_str DB Esc,'OM',0
-
-
- ; Scan codes for keys we have predefined ...
-
- Zero_key EQU 82 ; These are all the "keypad" keys
- One_key EQU 79
- Two_key EQU 80
- Three_key EQU 81
- Four_key EQU 75
- Five_key EQU 76
- Six_key EQU 77
- Seven_key EQU 71
- Eight_key EQU 72
- Nine_key EQU 73
-
- Period_key EQU 83
- Comma_key EQU 55 ; AKA "PrtSc *"
- Minus_key EQU 74
- Enter_key EQU 78 ; AKA "grey +"
-
- PF1_key EQU 59 ; Use PC's PF keys 1-4 as VT100 PF1-4
- PF2_key EQU 60
- PF3_key EQU 61
- PF4_key EQU 62
-
- PF5_key EQU 63 ; Clone VTERM, takes you to command level
- PF6_key EQU 64 ; As above, takes you to help
-
- PF7_key EQU 65 ; Up-arrow
- PF8_key EQU 66 ; Down
- PF9_key EQU 67 ; Left
- PF10_key EQU 68 ; Right ...
-
- CtrlPrtSc EQU 114 ; CTRL + */PrtSc keys (set up by BIOS)
-
- Scroll_lock_key EQU 70 ; Scroll Lock, aka BREAK
- Tab_key EQU 15 ; Tab key
-
-
- EVEN ; Try for word boundary
-
- ; Dispatch table for keyboard activity
-
- Key_codes LABEL WORD
- DW Zero_key, One_key, Two_key
- DW Three_key, Four_key, Five_key
- DW Six_key, Seven_key, Eight_key
- DW Nine_key, Period_key, Comma_key
-
- DW Minus_key, Enter_key, PF1_key
- DW PF2_key, PF3_key, PF4_key
- DW PF5_key, PF6_key, PF7_key
- DW PF8_key, PF9_key, PF10_key
-
- Number_of_key_codes EQU ( $ - Key_codes ) / 2
-
- Key_actions LABEL WORD
-
- Do_Zero_key DW If_keypad_application_mode_set
- DW Num_Zero_str
- DW Appl_Zero_str
-
- Do_One_key DW If_keypad_application_mode_set
- DW Num_One_str
- DW Appl_One_str
-
- Do_Two_key DW If_keypad_application_mode_set
- DW Num_Two_str
- DW Appl_Two_str
-
- Do_Three_key DW If_keypad_application_mode_set
- DW Num_Three_str
- DW Appl_Three_str
-
- Do_Four_key DW If_keypad_application_mode_set
- DW Num_Four_str
- DW Appl_Four_str
-
- Do_Five_key DW If_keypad_application_mode_set
- DW Num_Five_str
- DW Appl_Five_str
-
- Do_Six_key DW If_keypad_application_mode_set
- DW Num_Six_str
- DW Appl_Six_str
-
- Do_Seven_key DW If_keypad_application_mode_set
- DW Num_Seven_str
- DW Appl_Seven_str
-
- Do_Eight_key DW If_keypad_application_mode_set
- DW Num_Eight_str
- DW Appl_Eight_str
-
- Do_Nine_key DW If_keypad_application_mode_set
- DW Num_Nine_str
- DW Appl_Nine_str
-
- Do_Period_key DW If_keypad_application_mode_set
- DW Num_Period_str
- DW Appl_Period_str
-
- Do_Comma_key DW If_keypad_application_mode_set
- DW Num_Comma_str
- DW Appl_Comma_str
-
- Do_Minus_key DW If_keypad_application_mode_set
- DW Num_Minus_str
- DW Appl_Minus_str
-
- Do_Enter_key DW If_keypad_application_mode_set
- DW Num_Enter_str
- DW Appl_Enter_str
-
- Do_PF1_key DW Leave_alone
- DW PF1_str
- DW PF1_str
-
- Do_PF2_key DW Leave_alone
- DW PF2_str
- DW PF2_str
-
- Do_PF3_key DW Leave_alone
- DW PF3_str
- DW PF3_str
-
- Do_PF4_key DW Leave_alone
- DW PF4_str
- DW PF4_str
-
- Do_PF5_key DW Leave_emulator
- nop
- nop
- nop
- nop
-
- Do_PF6_key DW Call_Helper
- nop
- nop
- nop
- nop
-
- Do_PF7_key DW If_cursor_keys_mode_set
- DW Normal_PF7_str
- DW Alternate_PF7_str
-
- Do_PF8_key DW If_cursor_keys_mode_set
- DW Normal_PF8_str
- DW Alternate_PF8_str
-
- Do_PF9_key DW If_cursor_keys_mode_set
- DW Normal_PF9_str
- DW Alternate_PF9_str
-
- Do_PF10_key DW If_cursor_keys_mode_set
- DW Normal_PF10_str
- DW Alternate_PF10_str
-
-
- ; Alternate dispatch table for keyboard activity
-
- Key_codes_2 LABEL WORD
- DW Two_key, Four_key, Six_key
- DW Eight_key
-
- Number_of_key_codes_2 EQU ( $ - Key_codes_2 ) / 2
-
- Key_actions_2 LABEL WORD
-
- Do_Two_key_2 DW If_cursor_keys_mode_set
- DW Normal_PF8_str
- DW Alternate_PF8_str
-
- Do_Four_key_2 DW If_cursor_keys_mode_set
- DW Normal_PF9_str
- DW Alternate_PF9_str
-
- Do_Six_key_2 DW If_cursor_keys_mode_set
- DW Normal_PF10_str
- DW Alternate_PF10_str
-
- Do_Eight_key_2 DW If_cursor_keys_mode_set
- DW Normal_PF7_str
- DW Alternate_PF7_str
-
-
- ; Other alternate dispatch table for IBM 7171 keyboard activity
-
- Key_codes_7171 LABEL WORD
- DW Zero_key, One_key, Two_key
- DW Three_key, Four_key, Five_key
- DW Six_key, Seven_key, Eight_key
- DW Nine_key, Period_key, Comma_key
-
- DW Minus_key, Enter_key, PF1_key
- DW PF2_key, PF3_key, PF4_key
- DW PF5_key, PF6_key, PF7_key
- DW PF8_key, PF9_key, PF10_key
-
- X EQU (alt_shift * 256)
- ; X is the alt_shift flag shifted into the left half
-
- ; 104 and 105 are scan codes for ALT F1 and ALT F2
-
- DW X+104, X+105
-
- ; 120, 121 etc. are scan codes for top row digits 1 .. 0 followed by - and =
-
- DW X+120, X+121, X+122
- DW X+123, X+124, X+125
- DW X+126, X+127, X+128
- DW X+129, X+130, X+131
-
- DW Tab_key
- DW (left_shift * 256) + Tab_key
- DW 14 ; Backarrow
-
- Number_of_key_codes_7171 EQU ( $ - Key_codes_7171 ) / 2
-
- Key_actions_7171 LABEL WORD
- DW K71_Ins_str ; 0 (Ins) on numeric pad
- DW K71_End_str ; 1
- DW Alternate_PF8_str ; 2 (down)
- DW Null_string ; 3
- DW Alternate_PF9_str ; 4 (left)
- DW Null_string ; 5
- DW Alternate_PF10_str ; 6 (right)
- DW K71_Home_str ; 7
- DW Alternate_PF7_str ; 8 (up)
- DW Null_string ; 9
- DW K71_Del_str ; period (Del)
- DW Null_string ; Comma (PrtSc)
- DW K71_Erase_EOL_str ; Grey -
- DW Appl_Enter_str ; Grey +
- DW K71_PF1_str ; F1
- DW K71_PF2_str
- DW K71_PF3_str
- DW K71_PF4_str
- DW K71_PF5_str
- DW K71_PF6_str
- DW K71_PF7_str
- DW K71_PF8_str
- DW K71_PF9_str
- DW K71_PF10_str ; F10
- DW K71_PF11_str ; F11
- DW K71_PF12_str ; F12
- DW K71_PF1_str ; F1 again (on top row this time)
- DW K71_PF2_str
- DW K71_PF3_str
- DW K71_PF4_str
- DW K71_PF5_str
- DW K71_PF6_str
- DW K71_PF7_str
- DW K71_PF8_str
- DW K71_PF9_str
- DW K71_PF10_str ; F10
- DW K71_PF11_str ; F11
- DW K71_PF12_str ; F12 (end of top row)
- DW K71_Tab_str
- DW K71_Shift_Tab_str
- DW Alternate_PF9_str ; Backarrow, usually DELete, now = left arrow
-
-
- ; Table of max per-loop character counts based on baud rate
-
- Baud_Char LABEL WORD
- DW 1 ; 45.5 baud 1
- DW 1 ; 50 2
- DW 1 ; 75 3
- DW 1 ; 110 4
- DW 2 ; 135 5
- DW 3 ; 150 6
- DW 5 ; 300 7
- DW 10 ; 600 8
- DW 20 ; 1200 9
- DW 30 ; 1800 10
- DW 33 ; 2000 11
- DW 41 ; 2400 12
- DW 82 ; 4800 13
- DW 164 ; 9600 baud, enough for two full lines 14
- DW 164 ; 19200 baud 15
- DW 164 ; 23040 baud 16
- DW 164 ; 38400 baud 17
-
- Baud_table_size EQU 17 ; Number of baud rates known
-
-
- ; Maximum number of scrolls to do in a display cycle
-
- PUBLIC Maximum_scrolls
-
- Maximum_scrolls DW 1
-
-
- ; Strings sent in response to incoming escape sequences
-
- DA_str DB Esc,'[?1;2c',0 ; Standard answer (for VT100 with AVO) to
- ; Device Attributes (DA)
-
- ;DA_str DB Esc,'[?6c',0 ; Standard answer (for VT102) to
- ; Device Attributes (DA)
-
- DSR_str DB Esc,'[0n',0 ; The No Malfunctions answer to Device
- ; Status Request (DSR)
-
- CPR_str DB Esc,'[',0 ; First two chars in CPR esc seq
-
- Ident_str DB Esc,'[?99c',0 ; Code to say that we are not just a VT100
-
- No_memory DB Cr, Lf, '? Not enough memory for Terminal Emulation', Cr, Lf, '$'
-
- Lc DB ' lc ' ; For lower case
- CAPS DB 'CAPS' ; Caps lock
- Arrow DB 24,25,27,26 ; Up, down, left, right
- Num DB 'NumL' ; Num lock
-
-
- ; Table to translate graphic mode VT100 char into "best" IBM PC equivalent
-
- Graphic_translation_table LABEL BYTE
-
- DB 032 ; 95
- DB 004 ; 96
- DB 176 ; 97
- DB 029 ; 98
- DB 023 ; 99
- DB 017 ; 100
- DB 025 ; 101
- DB 248 ; 102
- DB 241 ; 103
- DB 174 ; 104
- DB 018 ; 105
- DB 217 ; 106
- DB 191 ; 107
- DB 218 ; 108
- DB 192 ; 109
- DB 197 ; 110
- DB 196 ; 111
- DB 196 ; 112
- DB 196 ; 113
- DB 196 ; 114
- DB 196 ; 115
- DB 195 ; 116
- DB 180 ; 117
- DB 193 ; 118
- DB 194 ; 119
- DB 179 ; 120
- DB 243 ; 121
- DB 242 ; 122
- DB 227 ; 123
- DB 247 ; 124
- DB 156 ; 125
- DB 250 ; 126
-
-
- ; Mode line templates -- attribute byte followed by string followed by
- ; NUL character (ASCII 0) -- two NULs in a row mark end-of-template
-
- Mode_template LABEL BYTE ; Mode line
-
- ; DB 70h,Space,Space,0
- ; DB 71h,'F5',0,70h,'=Command mode',Space,Space,Space,0
- ; DB 71h,'F6',0,70h,'=Help Esc chr=',0,71h
- DB 70h, ' '
- VerDef
- DB ' ',0
- DB 71h,'ALT-F6',0
- DB 70h,'=Help Esc chr=',0,71h
- M_Esc DB '^[',0,70h,Space,Space,Space,Space,0
- M_Prt DB 70h,' ',0
- M_Prt_length=$-M_Prt ; Length of this item
- DB 70h,Space,Space,Space,Space,0,71h
- M_Caps DB ' lc ',0,70h,Space,Space,Space,0,71h
- M_KPad DB 24,25,27,26,0
- DB 70h,Space,Space,Space,Space,0
- M_L1 DB 70h,'L1',0,70h,Space,0
- M_L2 DB 70h,'L2',0,70h,Space,0
- M_L3 DB 70h,'L3',0,70h,Space,0
- M_L4 DB 70h,'L4',0,70h,Space,Space,0
- DB 0
-
- M_Prt_On DB 71h,'Prt',0
- M_Prt_Off DB 70h,' ',0
-
- ; Template for "mode line" after user has hit the escape char
-
- Esc_chr_template LABEL BYTE
-
- DB 70h,Space,0
- DB 71h,'?',0,70h,'=Help',Space,Space,Space,Space,0
- DB 71h,'C',0,70h,'=Close',Space,Space,Space,Space,0
- DB 71h,'S',0,70h,'=Status',Space,Space,Space,Space,0
- DB 71h,'B',0,70h,'=send Break',Space,Space,Space,0
- DB 71h,'M',0,70h,'=Mode line',Space,Space,Space,Space,0
- DB 71h,'?',0,70h,' for full list',Space,0,0
-
- offmsg DB 'Off'
- onmsg DB 'On '
-
- EVEN ; Try for word boundary
-
- beldiv DW 2DCh ; 550 hz?
-
-
- ; Vt100 data, changeable ...
-
- ; Screen addressing data
-
- PUBLIC Max_number_of_chars, Number_of_chars_done, Image_ptr
-
- Max_number_of_chars DW 10 ; Max number of chars to do in Do_Screen
- Number_of_chars_done DW 0 ; How many chars we have done this pass
-
- Number_of_scrolls_done DW 0 ; Count of lines scrolled this display cycle
-
- Image_ptr DW ? ; Pointer to screen image, used by Put_Screen
-
-
- ; VT100 status flags and flag word
-
- Keypad_application_mode EQU 1 ; Determines data sent by keypad keys
- Cursor_keys_mode EQU 2 ; Determines data sent by arrow keys
- Private_esc_seq EQU 4 ; A q-mark was found in esc seq
- Printer_controller_mode EQU 8 ; Send all data to printer, not display
- Auto_copy_mode EQU 10h ; Send data to display AND printer
-
- Printer_wanted = Printer_controller_mode + Auto_copy_mode
-
- VT100_status_flags DB 0 ; Place to hold status flags
- Old_status_flags DB 0 ; Place to hold previous value
-
-
- ; Screen management flags
-
- Screen_open EQU 1 ; Command mode screen has already been saved
- Position_changed EQU 2 ; New position
- Line_changed EQU 4 ; Data on current line changed
- Screen_changed EQU 8 ; Data on more than one line changed
- Force_screen_update EQU 10h ; Update every character of both video pages,
- ; (on color card), which is slower than
- ; mollasses in January
-
- Changed EQU Position_changed + Line_changed + Screen_changed
-
- Screen_flags DB 0 ; Flags for managing the screen
-
- Hit_ESC DB 0 ; Flag to say we just hit an escape, used only
- ; while in printer controller mode
-
- Prev_shift_state DB 0FFh ; Set initial shift to something impossible
-
-
- ; Rendition / attribute data ...
-
- Bold EQU 1 ; Extra bright (SGR code 1)
- Underscored EQU 2 ; Underlined (SGR code 4)
- Blinking EQU 4 ; Blinking (SGR code 5)
- Inverted EQU 8 ; Inverse video (SGR code 7)
- Graphi EQU 10h ; Flag for graphics char set
-
- Rendition DB ? ; Currently set graphic rendition flags
- Attribute_Byte DB ? ; Current attribute
-
-
- ; VT100 LEDs L1 - L4
-
- LED1 EQU 1
- LED2 EQU 2
- LED3 EQU 4
- LED4 EQU 8
-
- LEDs DB 0 ; Start with all four LEDs off
-
- LoWork DB 10 DUP (Space) ; Low level work area, bigger than needed
-
-
- ; Scrolling region
-
- Top_margin DB ? ; Offset of top line in scrolling region
- Bottom_margin DB ? ; Offset of bottom line in scrolling region
-
-
- EVEN ; Try for word boundary
-
- Script_processor DW 0 ; Address of script processor to run
-
- Line_Ptr DW ? ; Address of first char on line we are on
- Char_Ptr DW ? ; Address of the char we are on
-
- Previous_char DB ? ; Most recently seen char
- Backed_up_char DB ? ; backed-up char
-
- Char_set DB ? ; Character set we are in
- G0_set DB ? ; G0 character set
- G1_set DB ? ; G1 character set
-
- ; One byte of quickly-clobbered junk, terminated with $ just-in-case
-
- Tmp DB ?, '$'
-
- ; Things saved by DECSC and restored by DECRC
-
- Save_char_set DB ? ; Saved char set number
- Save_G0_set DB ? ; Saved G0 char set
- Save_G1_set DB ? ; Saved G1 char set
- Save_rendition DB ? ; Saved rendition
- Save_position DW ? ; Saved cursor position
-
-
- ; Another saved item ...
-
- Save_SP_for_abort DW ? ; Place to save a stack ptr
-
-
- EVEN ; Try for word boundary
-
- ; Numbers read in during an escape sequence
-
- NumCnt DB ? ; The count of numbers we have stored
- NumPtr DB ? ; Which one we are on
- Nums DB 10 DUP (?) ; Numbers we have seen ...
-
- EBufLn EQU 128
- EBuffr DB EBufLn DUP (?) ; Escape buffer
- EBufGt DW ? ; Get ptr
- EBufPt DW ? ; Put ptr
- EBufCt DB ? ; Count of chars in buffer
-
- NewRow DB ? ; Place to put new row number
-
- ; Key redefinitions
-
- ktrntab DW ? ; address of translation table
- krpltab DW ? ; address of replacement table
- ktlen DW ?
-
- captrtn DW ? ; Routine to call for captured output
-
- portno DB ? ; Port number
-
- flags DB ? ; status flags, our copy of [bx].flg
-
- ; Things in flags1 ...
-
- prtscr EQU 80h ; print screen pressed
- lnwrap EQU 40h ; line wrap enabled
- inited EQU 08h ; been here before...
-
- flags1 DB 0 ; internal flags
-
- Esc_Ch DB ?
- argadr DW ? ; address of arg blk
-
- PUBLIC Cursor_position
-
- Cursor_position LABEL WORD ; Single name for both Column and Row
- Column DB ? ; Column we are in
- Row DB ? ; Row we are on
-
- Cursor DW ? ; Working place for Cursor pos
-
- DataS ENDS
-
-
- ; Dummy segment for allocated memory
-
- Alloc SEGMENT AT 0
-
- ;***************************************************************************
- ; The screen image, locally updated then blasted out to real screen memory
- ;***************************************************************************
-
- Number_of_rows EQU 24 ; Length in rows
- Number_of_columns EQU 80 ; Width in characters
- Highest_row EQU Number_of_rows-1; Highest row number
- Highest_column EQU Number_of_columns-1 ; Highest column number
- Lower_right EQU (100h*Highest_row) + Highest_column
- ; Lower right corner of virtual screen ...
- Number_of_chars_on_VT100_screen EQU Number_of_columns*Number_of_rows
- ; Number of chars in a VT100 screen
- Number_of_rows_PC EQU 25 ; Length in rows including mode line
- Number_of_chars_on_PC_screen EQU Number_of_columns*Number_of_rows_PC
- ; Number of chars in IBM screen
-
- EVEN ; Try for word boundary
-
- ; Display update list
-
- PUBLIC Update_list
-
- Update_list DW (2 * Number_of_chars_on_PC_screen) DUP (?) ; One word location
- ; info followed by one word of char/attr
- ; for each update item
-
- Alloc_cursor_position DW ? ; Copy of current cursor position
-
- PUBLIC Screen_Image, Mode_line
-
- Screen_Image DW Number_of_chars_on_VT100_screen DUP (?)
- ; The screen buffer itself
-
- ; Mode line, follows immediately after screen image
-
- Mode_line DW Number_of_columns DUP (?)
-
-
- ; The previous screen contents, used to build update list
-
- Old_Image DW Number_of_chars_on_PC_screen DUP (?)
-
-
- ; Contents of screen on entry to terminal emulator, restored on exit
-
- Command_mode_cursor DW ? ; Saved cursor position from command mode
- Command_mode_screen DW Number_of_chars_on_PC_screen DUP (?)
-
- End_Alloc LABEL BYTE
-
- Alloc ENDS
-
- ;***************************************************************************
-
-
- ; *Code* ...
-
- RetSkp MACRO ; Return skip
- jmp RSkp
- ENDM
-
- RetNop MACRO ; Return from subroutine, take up 3 bytes
- ret
- nop
- nop
- ENDM
-
-
- Code SEGMENT PUBLIC ; code segment
-
- EXTRN Quit_emulator:BYTE, Which_card:BYTE
- EXTRN PrtChr_PC:NEAR, OutChr_PC:NEAR, SendBr:NEAR, Helper:NEAR
- EXTRN SerIni_PC:NEAR, SerRst_PC:NEAR, Enter_Server:NEAR
- EXTRN Exit2:NEAR, Type_to_screen:NEAR, Force_card:BYTE
- EXTRN PosCur_PC:NEAR, Quick_Push:NEAR, ClrMod_PC:NEAR
- EXTRN Get_memory_block:NEAR, Set_up_video_card_pointers:NEAR
- EXTRN Go_to_page_zero:NEAR, Blank_current_page:NEAR
- EXTRN Switch_video_pages:NEAR, Beam_Off:NEAR, Beam_On:NEAR
-
- Datas_ds DW 0 ; Place to hold normal ds (DATAS)
- Alloc_ds DW 0 ; Place to hold ptr to allocated ds (ALLOC)
-
- Screen_Image_ptr DD 0 ; Doubleword pointer to VT100 image
- Mode_Line_ptr DD 0 ; Doubleword pointer to mode line
-
- Max_number_of_items DW 300 ; Max number of display update items to do
- ; during retrace in Update_nondisplayed_page
- Number_of_update_items DW 0 ; How many items in list?
-
-
- ASSUME cs:Code, ds:Datas, es:Datas
-
-
- ; Close out terminal emulation screen
-
- Close_Screen_PC PROC
-
- test Screen_flags, Screen_Open ; Should we restore?
- jz CLO_ret ; No
-
- call Restore_command_mode_screen ; Get back original screen
- and Screen_flags, NOT Screen_open ; Clear this flag
-
- CLO_ret:
- ret ; Done here
-
- Close_Screen_PC ENDP
-
-
- ; Perform terminal emulation
-
- Term_PC PROC ; terminal emulator entry point
-
- push es ; save caller's extra segment address
-
- mov argadr, ax ; save argument ptr
-
- mov ax, SEG datas
- mov es, ax
-
- call Set_up_dynamic_memory ; Try to get memory
- jnc TRM_0
-
- mov ah, PrStr ; Code to type message
- mov dx, OFFSET No_memory ; Complain about lack of memory
- int Dos ; Display it
-
- mov Quit_emulator, 1 ; Flag that we want out
- jmp TRM_S3 ; Quit the program
-
- TRM_0: call argini ; Initialize options from arg address
- call Enter_text_mode ; This program requires text mode
-
- call Set_up_video_card_pointers ; Learn video mode, card type, etc.
-
- test Screen_flags, Screen_open ; Is the screen already "open"?
- jnz TRM_2 ; All set, don't worry
-
- call Save_command_mode_screen ; Save it
- or Screen_flags, Screen_open ; Set flag for later
-
- TRM_2: test flags1, inited ; Have we run yet?
- jz TRM_3 ; No, go initialize everything
-
- call ReInit_Screen ; Display our screen buffer on the screen
- jmp SHORT TRM_5 ; Join common code
-
- TRM_3: call Initialize_Screen ; Initialize screen and buffers
- call Flush_esc_buffer ; Initialize pointers into escape buffer
- call Do_mode_line ; Do proper thing with the mode line
- call Do_our_screen ; Get screen up-to-date
- or flags1, inited ; Remember that we've done this already
-
- TRM_5: mov Quit_emulator, 0 ; Clear this flag
-
-
- ; First, try for chars from keyboard
-
- PUBLIC Trm_Kb
-
- TRM_Kb:
-
- ; Before we are allowed to really check the keyboard, we have to see if
- ; we are running under control of a script. If we are, we have to call
- ; it at its "keyboard" entry instead of reading from the keyboard.
-
- cmp Script_processor, 0 ; Is there a script processor to run?
- je TRM_No_script ; No
-
- TRM_Ck: mov ah, 1 ; Code to see if anything there
- int Kb ; Check input buffer
- jnz TRM_S0 ; Get char
-
- mov al, 0FFh ; Say we don't have a character
- jmp SHORT TRM_S1 ; Pass this along to the processor
-
- TRM_S0: sub ah, ah ; Code zero
- int Kb ; Get the char from the buffer
-
- TRM_S1: sub ah, ah ; Code for "keyboard" entry
- call Script_processor ; Let it do its thing
- test Quit_emulator, 1 ; Is this flag set?
- jz TRM_Scr ; No, try for more keyboard chars ...
-
- TRM_S3: call Close_Screen_PC ; Go set things up right for command mode
- jmp SHORT TRM_Quit ; Go back to other program
-
- TRM_No_script:
- mov ah, 1 ; Code to see if anything there
- int Kb ; Check ...
- jz Trm_Scr ; nothing available...
-
- sub ah, ah ; Code zero
- int Kb ; get the char from the buffer
-
- push ax ; save character temporarily
- call GSS ; get shift state into al
- mov bl, al ; save shift state
- pop ax
-
- cmp al, Esc_Ch ; Escape character?
- jne TRM_Key ; No, go deal with the character
-
- mov si, OFFSET Esc_chr_template ; The template giving help for
- ; the escape char
- call Build_mode_line ; Turn it into a mode line
- call Do_our_screen ; Display it
- jmp SHORT TRM_Quit ; Go finish up here
-
- TRM_Key:
- call Handle_keystroke ; Do whatever is required for this keystroke
-
- test Quit_emulator, 1 ; Is this flag set?
- jz TRM_Kb ; No, try for more keyboard chars ...
-
- call Close_Screen_PC ; Go set things up right for command mode
- jmp TRM_Quit ; Go back to other program
-
-
- ; Second, handle any buffered port characters
-
- PUBLIC TRM_Scr
-
- TRM_Scr:
- call Do_Screen ; Call routine to process all buffered
- ; characters received over the comm port
- test Quit_emulator, 1 ; Is this flag set?
- jz TRM_Kb ; No, try for more keyboard chars ...
-
- call Close_Screen_PC ; Go set things up right for command mode
- ; jmp TRM_Quit ; Go back to other program
-
-
- ; User hit the magic character, leave this routine to see what he wants
-
- TRM_Quit:
- call Go_to_page_zero ; Be on page zero in display memory
-
- cmp Script_processor, 0 ; Is there a script processor active?
- je TRM_q_no_script ; No
-
- mov ah, 2 ; Code to shutdown
- call Script_processor ; Shut him down
-
- TRM_q_no_script:
- mov al, flags
- mov bx, argadr
- mov [bx].flgs, al ; update flags in arg block
- pop es ; restore segment register
-
- ret ; and return to caller
-
- Term_PC ENDP
-
-
- ; Initialize internal variables based on argument block we were passed
-
- argini PROC ; read passed arguments
-
- mov bx, argadr ; base of argument block
- mov al, [bx].flgs ; get flags
- and al, capt + havtt + lclecho + modoff
- mov flags, al ; mask for allowable and save
-
- mov al, [bx].prt
- mov portno, al ; update port number
-
- mov ax, [bx].captr
- mov captrtn, ax ; buffer capture routine
-
- mov ax, [bx].belld
- mov beldiv, ax ; bell divisor
-
- mov ax, [bx].klen
- mov ktlen, ax ; length of key redef tbl
-
- mov ax, [bx].ktab
- mov ktrntab, ax ; save key translation table
-
- mov ax, [bx].krpl
- mov krpltab, ax
-
- mov al, [bx].escc
- mov Esc_ch, al
-
- mov ax, 4 ; Get a 4
- mov Max_number_of_chars, ax ; Store it as default
-
- mov al, [bx].BaudB ; Get baud bits
- cmp al, Baud_table_size ; Too big?
- jnb ARG_1 ; Yes, use the default
-
- shl al, 1 ; Double for word offset
- cbw ; Make full word
- mov bx, ax ; Copy to bx
- mov ax, Baud_Char[bx] ; Pick up the value for this baud rate
- mov Max_number_of_chars, ax ; Install as the per-loop limit
- ; in Do_Screen
-
- ARG_1: ret ; That's it
-
- argini ENDP
-
-
- Set_up_dynamic_memory PROC
-
- cmp Alloc_ds, 0 ; Is this already set up?
- jnz SDM_OK ; Yes, don't do another
-
- mov bx, OFFSET End_Alloc+15 ; Round up to next paragraph
- mov cl, 4 ; Shift count
- shr bx, cl ; Shift to get number of paras we need
-
- call Get_memory_block ; Get a memory block of the right size
- jc SDM_ret ; NG, die
-
- mov Alloc_ds, ax ; Save the address of our block
-
- mov WORD PTR Screen_Image_ptr+2, ax ; Save it here also ...
- mov WORD PTR Mode_Line_ptr+2, ax ; and here ...
-
- mov ax, OFFSET Screen_Image ; Offset of the screen image in its seg
- mov WORD PTR Screen_Image_ptr, ax ; Save for other users
-
- mov ax, OFFSET Mode_Line ; Offset of the mode line
- mov WORD PTR Mode_Line_ptr, ax ; Save it also
-
- mov ax, Datas ; Get ptr to DataS segment
- mov Datas_ds, ax ; Save it here
-
- SDM_OK: clc ; No error
-
- SDM_ret: ret
-
- Set_up_dynamic_memory ENDP
-
-
- ; Initialize internal screen buffer to blanks, put cursor in upper
- ; left corner of screen
-
- PUBLIC Initialize_screen, Rendition, Screen_flags
-
- Initialize_Screen PROC ; init screen stuff
-
- VTFlags = Keypad_application_mode + Cursor_keys_mode
-
- and VT100_status_flags, NOT VTFlags ; Turn off all relevant flags
-
- sub al, al ; Get a zero
- mov Char_set, al ; In char set 0
- mov G0_set, al ; This set is non-graphics
- mov G1_set, al ; This set is non-graphics also
- mov Rendition, al ; Normal rendition
- mov Attribute_Byte, 7 ; Normal screen attribute (white on black)
-
- mov Top_margin, al ; Zero top of scrolling region
- mov al, Highest_row ; Get number of highest row on VT100 screen
- mov Bottom_margin, al ; Save as bottom of scrolling region
-
- mov ax, Alloc_ds ; Ptr to allocated data segment
- mov es, ax ; Load into es
- ASSUME es:Alloc
-
- cld ; Move forward
-
- mov ax, 0720h ; Normal video blank
- mov cx, Number_of_chars_on_PC_screen ; Number of bytes to lay down
- mov di, OFFSET Screen_Image ; Where to put the bytes
- rep stosw ; Zap the buffer
-
- mov cx, Number_of_chars_on_PC_screen ; Number of bytes to lay down
- mov di, OFFSET Old_Image ; Where to put the bytes
- rep stosw ; Zap the buffer
-
- mov ax, Datas_ds ; Ptr to normal data segment
- mov es, ax ; Load into es
- ASSUME es:Datas
-
- cmp cs:Which_card, 1 ; Color card?
- jne ISC_2 ; Nope, skip this
-
- call Blank_current_page ; Clear page zero
- call Switch_video_pages ; Switch to the other page
- call Blank_current_page ; Clear page one
- call Switch_video_pages ; Switch back to the first page
-
- ISC_2: sub ax, ax ; Make a zero
- mov Cursor_position, ax ; Store as cursor position
- jmp Set_pointers ; Go set up ptrs, return from there
-
- Initialize_Screen ENDP
-
-
- ; Re-initialize screen ... we have run this module before, but the
- ; screen needs to be fully restored
-
- PUBLIC ReInit_Screen
-
- ReInit_Screen PROC ; init screen stuff
-
- mov ax, Alloc_ds ; Ptr to allocated segment
- mov ds, ax ; Set ds to it
- nop ; Be nice to debugger
- mov es, ax ; es also
- ASSUME ds:Alloc, es:Alloc
-
- mov si, OFFSET Screen_Image
- mov di, OFFSET Old_Image
- mov cx, Number_of_chars_on_PC_screen
- cld ; Forwards
- rep movsw ; Force old image to match the screen
-
- mov ax, Datas_ds ; Ptr to allocated segment
- mov ds, ax ; Set ds to it
- nop ; Be nice to debugger
- mov es, ax ; es also
- ASSUME ds:Datas, es:Datas
-
- call Do_Mode_Line ; Make sure mode line is up-to-date
- call Set_up_video_card_pointers ; Adapt to the current card
-
- call Beam_Off ; Suppress video during copy of screen
- mov si, OFFSET Screen_Image ; Source OFFSET within segment
- sub di, di ; Start at zero
- mov cx, Number_of_chars_on_PC_screen ; Full PC screen
- push es ; Save reg
- ASSUME es:Nothing
- call Get_Screen_Segment ; Get address of our screen
- mov es, ax ; Install it
-
- mov ax, Alloc_ds ; Segment that holds the Screen_Image
- mov ds, ax ; which we must copy from
- ASSUME ds:Alloc
-
- cld ; Forwards
- rep movsw ; Blast out the screen
- pop es ; Get back reg
- ASSUME es:Datas
-
- mov ax, Datas_ds ; Normal segment
- mov ds, ax ; Restore it
- ASSUME ds:Datas
-
- call Beam_On ; Re-enable video
- mov ah, 2 ; Code to set cursor position
- sub bh, bh ; Page zero
- mov dx, Cursor_position ; Set up cursor position
- int Screen ; Do it
-
- ; We just updated the visible screen, now update the invisible one ...
- ; ... this is very slow (which is why we updated the visible screen first).
-
- or Screen_flags, Force_screen_update ; Do a whole lot of work
- jmp Do_our_screen ; Use standard routine to install it,
- ; return from there
-
- ReInit_Screen ENDP
-
-
- ; Save and restore command mode screen
-
- PUBLIC Save_command_mode_screen
-
- Save_command_mode_screen PROC
-
- call Beam_Off ; Suppress video during copy of screen
- sub si, si ; Start at zero
- mov di, OFFSET Command_mode_screen ; Destination OFFSET within segment
- mov cx, Number_of_chars_on_PC_screen ; Full PC screen
- push ds ; Save ds
- call Get_Screen_Segment ; Get address of our ds
- mov ds, ax ; Install it
- mov ax, Alloc_ds ; Pick up ptr to allocated segment
- mov es, ax ; Set up in es -- Command_mode_screen's seg
- ASSUME es:Alloc
- cld ; Forwards
- rep movsw ; Blast out the screen
- pop ds ; Get back ds
- mov ah, 3 ; Code to read cursor position
- sub bh, bh ; Page zero
- int Screen ; Get cursor position
- mov Command_mode_cursor, dx ; Save for later
- mov ax, Datas_ds ; Pick up normal ds
- mov es, ax ; Reinstall in es
- ASSUME es:DataS
- jmp Beam_On ; Re-enable video
-
- Save_command_mode_screen ENDP
-
- Restore_command_mode_screen PROC
-
- call Go_to_page_zero ; Be on page zero in display memory
- call Beam_Off ; Suppress video during copy of screen
- mov si, OFFSET Command_mode_screen ; Source OFFSET within segment
- sub di, di ; Start at zero
- mov cx, Number_of_chars_on_PC_screen ; Full PC screen
- push es ; Save reg
- call Get_Screen_Segment ; Get address of our screen
- mov es, ax ; Install it
- mov ax, Alloc_ds ; Pick up ptr to allocated segment
- mov ds, ax ; Set up in ds -- Command_mode_screen's seg
- ASSUME ds:Alloc
- cld ; Forwards
- rep movsw ; Blast out the screen
- pop es ; Get back reg
- mov ah, 2 ; Code to set cursor position
- sub bh, bh ; Page zero
- mov dx, Command_mode_cursor ; Get back saved cursor position
- int Screen ; Set cursor position
- mov ax, Datas_ds ; Pick up normal ds
- mov ds, ax ; Reinstall in es
- ASSUME ds:DataS
- jmp Beam_On ; Re-enable video
-
- Restore_command_mode_screen ENDP
-
-
- ; Assemble mode line, then install in screen buffer
-
- PUBLIC Do_mode_line
-
- Do_mode_line PROC
-
- test flags, modoff ; Is the mode line disabled?
- jz DML_Do_it ; No, go draw it
-
- jmp Erase_mode_line ; Blow away old mode line, ret from there
-
- DML_Do_it:
- mov ah, 2 ; Code to get shift states
- int Kb ; Get them
-
- mov dx, ax ; Save state for later
-
- mov al, Esc_ch ; Get the escape character
- cmp al, Space ; Is it a control char?
- jge DML_No_carat ; No, don't type the carat
-
- mov M_Esc,'^' ; Store a carat
- add al, 40h ; Convert char to printable version
- mov M_Esc + 1, al ; Store the fixed-up char
- jmp SHORT DML_Print ; Skip code for no carat
-
- DML_No_carat:
- mov M_Esc, al ; Store the char
- mov M_Esc + 1, Space ; Space following
-
- DML_Print:
- mov si, OFFSET M_Prt_Off ; Assume printing is off
-
- test VT100_status_flags, Printer_wanted ; In one of these modes?
- jnz DML_Print_on ; Yes, say Prt is on
-
- test flags1, prtscr ; Should we be printing?
- jz DML_Write_Prt ; No
-
- DML_Print_on:
- mov si, OFFSET M_Prt_On ; Printing is on
-
- DML_Write_Prt:
- mov di, OFFSET M_Prt ; Where to write the data
- mov cx, M_Prt_length ; The number of chars to copy
- cld ; Forwards
- rep movsb ; Copy the bytes into the mode line
-
- mov di, OFFSET M_Caps ; Put data here
- mov si, OFFSET Caps ; String to say CAPS
- mov cx, 4 ; Number of bytes
- test dl, Caps_State ; Is it set?
- jnz DML_KPad ; We are in CAPS state, go say so
-
- mov si, OFFSET Lc ; Not in CAPS state
- DML_KPad:
- rep movsb ; Copy the bytes
-
- mov di, OFFSET M_KPad ; Put data here
- mov si, OFFSET Num ; String to say NumL
- mov cx, 4 ; Number of bytes
- test dl, Num_State ; Is it set?
- jnz DML_LED ; We are in Num state, go say so
-
- mov si, OFFSET Arrow ; Not in Num state
- DML_LED:
- rep movsb ; Copy the bytes
-
- mov al, 70h ; Normal
- test LEDs, LED1 ; Is this LED lit?
- jz DML_L1 ; No
-
- mov al, 0f0h ;
- DML_L1: mov M_L1, al ; Set attr for this LED
-
- mov al, 70h ; Normal
- test LEDs, LED2 ; Is this LED lit?
- jz DML_L2 ; No
-
- mov al, 0f0h ;
- DML_L2: mov M_L2, al ; Set attr for this LED
-
- mov al, 70h ; Normal
- test LEDs, LED3 ; Is this LED lit?
- jz DML_L3 ; No
-
- mov al, 0f0h ;
- DML_L3: mov M_L3, al ; Set attr for this LED
-
- mov al, 70h ; Normal
- test LEDs, LED4 ; Is this LED lit?
- jz DML_L4 ; No
-
- mov al, 0f0h
- DML_L4: mov M_L4, al ; Set attr for this LED
-
- mov si, OFFSET Mode_template ; Start at beginning
-
- ; Fall through to ...
-
- ; Build mode line -- Use assembled template to generate the mode line
-
- ; Call with
- ; si/ ptr to template to use
-
- Build_mode_line:
- call Erase_mode_line ; Erase any existing mode line
- mov di, OFFSET Mode_line ; Store the mode line here
-
- mov ax, Alloc_ds ; Ptr to Allocated data segment
- mov es, ax ; Set up es
- ASSUME es:Alloc
-
- Next_Attr:
- lodsb ; Pick up attribute
- or al, al ; End-of-the-line?
- je BML_End ; Done building mode line
-
- cmp Force_mono, 0 ; Are we stuck with mono no matter what?
- jne Do_mono ; Yes
-
- cmp CRT_Mode, 7 ; Monochrome card?
- jne Use_attr ; Color, use what we have set up
-
- ; Monochrome card does rude things to attributes that look nice in color
- ; Use different attributes
-
- Do_mono:
- cmp al, 71h ; Highlighted?
- jne Use_attr ; No
-
- mov al, 70h ; Be a square, leave it just inverted
-
- Use_attr:
- mov bl, al ; Save attr in bl
-
- Next_Char:
- lodsb ; Get the next char
- or al, al ; Done with this attr?
- je Next_Attr ; Yes, go try for another
-
- stosb ; Store the byte in the mode line
- mov al, bl ; Get the current attr
- stosb ; Store it too
- jmp Next_Char ; Go do another char
-
- BML_End:
- mov ax, Datas ; Ptr to normal data segment
- mov es, ax ; Restore es
- ASSUME es:Datas
-
- ret
-
- Do_mode_line ENDP
-
-
- ; Set internal mode line to normal video spaces
-
- Erase_mode_line PROC
-
- mov di, OFFSET Mode_line ; Ptr to mode line
- mov cx, Number_of_columns ; Number of words in the line
-
- mov ax, Alloc_ds ; Ptr to allocated ds
- mov es, ax ; Install in es
- ASSUME es:Alloc
-
- mov ax, 0720h ; Normal blanks
- cld ; Moving forwards
- rep stosw ; Store this in the whole line
-
- mov ax, Datas_ds ; Ptr to normal ds
- mov es, ax ; Install in es
- ASSUME es:Datas
-
- or Screen_flags, Screen_changed ; Flag screen change
- ret ; Done here
-
- Erase_mode_line ENDP
-
-
- ; Routine to get as many chars from port as possible,
- ; and update screen accordingly
-
- PUBLIC Do_screen
-
- Do_Screen PROC
-
- cmp Count, 0 ; Are there any chars we haven't seen already?
- jne DOS_1 ; Yes, deal with them
-
- jmp No_more_chars ; No chars, don't waste time here
-
- DOS_1: sub ax, ax ; Get a zero
- mov Previous_char, al ; No last character
- mov Backed_up_char, al ; No backed-up character
- mov Number_of_chars_done, ax ; Haven't done any chars yet
- mov Number_of_scrolls_done, ax ; These either
-
- mov ax, OFFSET EBuffr ; Get pointer to beginning of esc buffer
- mov EBufGt, ax ; Save as new getter ptr so we will pick
- ; up any sequence already partially read
-
- mov Save_SP_for_abort, sp ; Save a copy of the current stack ptr
- ; in case we have to blow out an escape seq
- ; in the middle ...
-
- PUBLIC Get_next_char
-
- Get_next_char:
-
- cmp Allow_blast, 0 ; Flag set?
- jnz Got_1 ; Yes, skip this test
-
- mov ax, Number_of_chars_done ; Number done so far
- cmp ax, Max_number_of_chars ; Too many?
- jl Got_1 ; Not yet
-
- jmp No_more_chars ; Did all we`re allowed, pretend no more
-
- Got_1: inc ax ; Bump by one
- mov Number_of_chars_done, ax ; Store updated count
-
- mov al, VT100_status_flags ; Get current status flags
- mov Old_status_flags, al ; Save for later
-
- Call PullCh ; Get a char from somewhere
- jmp No_more_chars ; No char to get, done here
-
- cmp al, Esc ; Is it an escape?
- jne GNC_1 ; No
-
- mov Hit_ESC, 0FFh ; Flag that we hit an escape
- jmp Do_Escape ; Go handle it
-
- GNC_1: mov Hit_ESC, 0 ; Not in an esc seq
- test VT100_status_flags, Printer_controller_mode ; In funny mode?
- jz GNC_2 ; No, deal with it as usual
-
- jmp SHORT Done_with_char ; In this mode we mostly ignore chars
-
- GNC_2: cmp al, Space ; Compare with space ...
- jge Do_Add ; If space or greater, just add it
-
- mov bx, OFFSET ActTb1 ; Action table
- mov cx, NChrTb1 ; Number of chars to check
- mov dx, OFFSET ChrTb1 ; Character table to use
- jmp SHORT Check_Table ; Do the lookup and dispatch
-
-
- ; Add this char to the stored line
-
- Do_Add: call Add_this_char ; Add this char, fall thru to ...
-
-
- ; Done_with_char == Bottom of loop:
- ;
- ; If we were if "Printer Controller Mode" when we started this and we
- ; are still in it now, then now is the time to dump the sequence to
- ; the printer.
- ; This lets all intended ESC sequences make it to the printer, but
- ; suppresses both the $[5i that puts us into Printer Controller Mode
- ; (because we were not in the Mode to start) and the $[4i that makes
- ; us leave the mode (because we are not in the mode now).
- ;
- ; Close out any active Esc sequence.
- ;
- ; Go see if there are any more characters to be read.
-
- PUBLIC Done_with_char
-
- Done_with_char:
-
- mov ax, OFFSET EBuffr ; Get pointer to beginning of esc buffer
- mov EBufGt, ax ; Save as new getter ptr so we will pick
- ; up any sequence that we have just read
-
- test flags1, prtscr ; Should we be printing?
- jnz DWC_Print ; Yes
-
- ; Printer_wanted = Printer_controller_mode + Auto_copy_mode
-
- test VT100_status_flags, Printer_wanted ; In a print mode?
- jz DWC_0 ; No
-
- test Old_status_flags, Printer_wanted ; Were we before?
- jz DWC_0 ; No
-
- DWC_Print:
- mov bx, EBufGt ; Escape buf getter ptr
- cmp bx, EBufPt ; Compare with putter ptr
- je DWC_0 ; If same, no chars held there
-
- mov dl, [bx] ; Pick up the char
- inc EBufGt ; Bump the ptr
- mov ah, LstOut ; Code to print a character
- int DOS ; Print this character
-
- jmp DWC_Print ; See if any more to do
-
-
- DWC_0: sub al, al ; Make a zero
- mov Backed_up_char, al ; Clobber "backed-up" char
- call Flush_esc_buffer ; Trash escae buffer
-
- cmp Quit_emulator, 0 ; Are we quitting?
- jne No_more_chars ; Yes
-
- cmp Allow_blast, 0 ; Flag set?
- jnz DWC_1 ; Yes, skip slowdown test
-
- mov ax, Number_of_scrolls_done
- cmp ax, Maximum_scrolls ; Scrolled enough to have to stop and update?
- jge No_more_chars ; Yes
-
- DWC_1: jmp Get_next_char ; Do more
-
- ; Abort processing, possibly in the middle of decoding an esc seq
-
- Abort_esc_sequence:
-
- mov sp, Save_SP_for_abort ; Get back saved stack pointer
- jmp Done_with_char ; Go clean it up
-
-
- ; Leaving screen update state, install buffer in screen memory if required
-
- PUBLIC No_more_chars
-
- No_more_chars:
-
- mov ah, 2 ; Code to get shift state
- int KB ; Get it
-
- and al, Num_state + Caps_state ; Check only these
- cmp al, Prev_shift_state ; Did something change?
- je End_of_pass ; No
-
- mov Prev_shift_state, al ; Save for next time
- call Do_mode_line ; Go make a new mode line
-
- End_of_pass:
-
- test Screen_flags, Changed ; Did something change?
- jz EOP_1 ; No
-
- jmp Do_our_screen ; Use standard routine to install it,
- ; return from there
-
- EOP_1: ret ; Done here
-
- Do_Screen ENDP
-
-
- ; Routine to search a table of chars for a desired char, then
- ; dispatch to another routine based on where the string was found,
- ; or if it was not found
- ;
- ; Call with ...
- ; al/ char to search for
- ; bx/ table of jump addresses (each entry one word) ... number of
- ; entries is one greater than number of entries in search
- ; table -- final entry is used if the search fails
- ; cx/ number of bytes in search table
- ; dx/ table to search in (each entry one byte)
- ; Trashes most of these, also di ...
-
- Check_Table PROC
-
- mov di, dx ; Copy over addr of table
- cld ; Forwards
- repne scasb ; Search for char in table
- jne Chk_1 ; If search failed, don't back up ptr
-
- dec di ; Drop by one due to REPNE overshoot
-
- Chk_1: sub di, dx ; Get index of char
- shl di, 1 ; Double for word offset
- add bx, di ; Add displacement to base of action table
- jmp WORD PTR [bx] ; Dispatch to the desired routine
-
- Check_Table ENDP
-
-
- ; Routine to flush the Escape buffer
-
- Flush_esc_buffer PROC
-
- mov ax, OFFSET EBuffr ; Address of Escape buffer
- mov EBufGt, ax ; Set up as getter ptr
- mov EBufPt, ax ; Set up as putter ptr also
- mov EBufCt, 0 ; Clear ebuf count
- mov Hit_ESC, 0 ; Not in an esc seq now
- ret ; Done here
-
- Flush_esc_buffer ENDP
-
-
- ;******************************************************************************
-
- ; *General utilities ...
-
- ; Get shift state into al. We only care about shift, ctl, and alt keys.
- ; Right shift is collapsed into left shift.
-
- Gss PROC
-
- mov ah, 2
- int Kb ; get current shift state
-
- mov bl, al ; copy for a moment
- and bl, right_shift ; mask out all but right shift
- shl bl, 1 ; move right shift to left shift pos
- or al, bl ; collapse shift bits
- and al, (left_shift + alt_shift + ctl_shift)
- ret
-
- Gss ENDP
-
-
- ; Send_char_to_port -- Send the character in al out to the serial port
-
- ; Call with
- ; al/ char to be sent
-
- Send_char_to_port PROC
-
- test flags, lclecho ; Local echo on?
- jz SCP_Noecho ; No
-
- call Type_to_screen ; Echo every character immediately
-
- SCP_Noecho:
- mov ah, al ; this is where outchr expects it
- call OutChr_PC ; output to the port
- RetNop
-
- ret
-
- Send_char_to_port ENDP
-
-
- ; Returns with carry on if a character is available
-
- PUBLIC Get_char_from_port
-
- Get_char_from_port PROC
-
- push dx ; PrtChr_PC clobbers dx
- call PrtChr_PC ; Character at port?
- jmp SHORT portc1 ; Yes, go handle
- nop ; 3 bytes
-
- clc ; No carry -> no character
- jmp SHORT portc2 ; Go finish up
-
- portc1: and al, 7Fh ; We don't worry about parity here
- stc ; Have a character
-
- portc2: pop dx ; Get back saved reg
- ret ; and return
-
- Get_char_from_port ENDP
-
-
- PUBLIC Handle_keystroke
-
- Handle_keystroke PROC
-
- push ax ; Save original value
-
- mov al, ah ; put scan code into al
- mov ah, bl ; shift state into ah
-
- cmp ax, (256*ctl_shift) ; Is this control-break?
- jne Not_Break ; No
-
- pop ax ; Fix stack
-
- mov ah, DConIo
- mov dl, 0FFh
- int Dos ; Read the bogus ^C DOS gets
-
- jmp SendBr ; Use other routine to send the break
-
- Not_Break:
- cmp ax, (ctl_shift*256)+CtrlPrtSc
- jne Not_PrtSc
-
- call trnprs ; Toggle the print screen setting
- pop ax
- ret
-
- Not_PrtSc:
- cmp ax, (ctl_shift*256)+57 ; Control-space?
- jne Not_Ctrl_Space ; No
-
- sub al, al ; Want a null
- call Send_char_to_port ; Send it out
- pop ax ; Get back saved reg
- ret ; Done here
-
- Not_Ctrl_Space:
- cmp ax, (alt_shift*256)+108 ; Alt F5?
- jne Not_ALT5 ; No
-
- pop ax
- jmp Leave_emulator ; Want to get out
-
- Not_ALT5:
- cmp ax, (alt_shift*256)+109 ; ALT F6?
- jne Not_ALT6 ; No
-
- pop ax
- jmp Call_Helper ; Call the help module
-
- Not_ALT6:
- cmp ax, (alt_shift*256)+110 ; ALT F7?
- jne Not_ALT7 ; No
-
- pop ax
- jmp Leave_program ; Want to get all the way out
-
- Not_ALT7:
- cmp ax, (alt_shift*256)+111 ; ALT F8?
- jne Not_ALT8 ; No
-
- pop ax
- call Go_to_page_zero ; Go to base page
- mov dx, (256*24) + 0 ; Lower left corner of screen
- call PosCur_PC ; Go there
- call ClrMod_PC ; Erase mode line (it's in inverse video)
- call Quick_Push ; Push directly from here
- nop ; Skips on success
- nop
- nop
- call SerIni_PC ; In case it got turned off ...
- or Screen_flags, Force_screen_update ; Update the world
- jmp Do_our_screen ; Restore our screen, ret from there
-
- Not_ALT8:
- cmp m7171, 0 ; In 7171 mode?
- jz Not_7171 ; No
-
- mov cx, Number_of_key_codes_7171 ; Number of entries to check
- mov dx, OFFSET Key_codes_7171 ; Scan code table to use
- mov di, dx ; Copy over addr of table
- cld ; Forwards
- repne scasw ; Search for word in table
- jne HAN_1 ; Search failed, go do something else
-
- mov bx, OFFSET Key_actions_7171 ; Action table for 7171 mode
- mov cx, di ; Copy to cx
- dec cx ; Drop by one word due to REPNE overshoot
- dec cx ; ...
- sub cx, dx ; Get index of char
- add bx, cx ; Add displacement to base of action table
- mov si, [bx] ; Pick up addr of string to send
- call Send_str_to_port ; Send it out
- pop ax ; Get back reg
- ret ; Done here
-
-
- %OUT >> About half way through source file
-
-
- Not_7171:
- mov cx, Number_of_key_codes ; Number of entries to check
- mov dx, OFFSET Key_codes ; Scan code table to use
- mov di, dx ; Copy over addr of table
- cld ; Forwards
- repne scasw ; Search for word in table
- jne HAN_1 ; Search failed, go do something else
-
- mov bx, OFFSET Key_actions ; Action table
- mov cx, di ; Copy to cx
- dec cx ; Drop by one word due to REPNE overshoot
- dec cx ; ...
- sub cx, dx ; Get index of char
- add bx, cx ; Add displacement to base of action table
- add bx, cx ; Double the offset
- add bx, cx ; Triple it (6 bytes instead of 2)
- lea dx, 2[bx] ; Get 2 + <addr of <addr of routine>> into dx
- call WORD PTR [bx] ; Dispatch to the desired routine, but come
- ; back when done ...
-
- pop ax ; Get back reg
- ret ; Done here
-
-
- ; Translate the scan code in ah according to the translate table
- ; given in ktrntab/krpltab, output to port. If no translation,
- ; use ascii char in al.
-
- HAN_1: test flags, havtt ; translate table given?
- jnz HAN_2 ; Yes, check it out
-
- pop ax ; Get back reg
- jmp SHORT HAN_3 ; Go output it normally
-
- HAN_2: mov di, ktrntab ; pick up translate tbl
- mov cx, ktlen ; length of tbl
- cld ; Forwards
- repne scasw ; look for our key
-
- pop ax ; recover character
- jne HAN_3 ; not found, forget it
-
- sub di, ktrntab ; get index into tbl
- sub di, 2 ; (minus 2 for pre-increment)
- mov bx, krpltab ; get replacement table
- mov si, [bx][di] ; and addr of replacement
- mov al, [si] ; Get first byte (length)
- cbw ; Blow up
- mov bx, ax ; Copy to bx
- inc si ; Point to translation string
- sub al, al ; Get a zero
- mov [si][bx], al ; Tie off the string at its declared length
- jmp Send_str_to_port ; Send it off to the port
-
- HAN_3: call Send_char_to_port ; just output single char
- ret ; and return
-
- trnprs: xor Flags1, PrtScr ; Flip the flag
- mov Prev_shift_state, 0FFh ; Store an impossible setting to force
- ; a redraw of mode line
- ret
-
- Handle_keystroke ENDP
-
-
- ; puts current screen segment in ax
-
- Get_screen_segment PROC
-
- mov ax, 0b000h ; assume bw for now
- cmp CRT_Mode, 7 ; 7 is bw (***)
- je scrse1
-
- mov ax, 0b800h ; color card
-
- scrse1: ret
-
- Get_screen_segment ENDP
-
-
- ; Do_our_screen -- Internal routine to set up for and call Put_Screen
-
- Do_our_screen PROC
-
- mov ax, Alloc_ds ; Pick up ptr to allocated ds
- mov es, ax ; Install in es
- ASSUME es:Alloc
- mov ax, Cursor_position ; Pick up cursor pos from DATAS segment
- mov Alloc_cursor_position, ax ; Install it in the Alloc segment
-
- mov bx, OFFSET Screen_image ; Ptr to our internal screen image
- call Put_Screen
-
- mov ax, Datas_ds ; Restore normal pointer ...
- mov es, ax ; to es
- ASSUME es:Datas
- ret ; DOne here
-
- Do_our_screen ENDP
-
-
- ; Put_Screen -- Copy a new screen image and mode line into display memory
-
- ; call with
- ; es:bx/ ptr to image to put on the screen, compared to old image
-
- PUBLIC Put_Screen
-
- Put_Screen PROC
-
- ASSUME es:Nothing
- mov Image_ptr, bx ; Save parameter
- sub bx, 2 ; Back up to Cursor pos
- mov ax, es:[bx] ; Pick it up
- mov Cursor, ax ; Store in local variable
-
- cld ; Forwards
-
- test Screen_flags, Screen_changed + Line_changed + Force_screen_update
- jz PSC_Position ; If only position changed, update only it
-
- cmp cs:Which_card, 1 ; Color card?
- je PSC_Color ; Yes, go do strange update
-
- mov si, Image_ptr ; Source for transfer
- push ds ; Save ds
- push es ; Save es
- mov ax, es ; Copy es
- mov ds, ax ; to ds
- mov ax, 0B000h ; Address of mono card memory
-
- cmp cs:Which_card, 2 ; Is this really the EGA in color mode?
- jne Not_EGA ; No
-
- mov ax, 0B800h ; EGA in color mode, use color address
-
- Not_EGA:
- mov es, ax ; Install in es reg
- sub di, di ; Destination OFFSET within segment
- mov cx, Number_of_chars_on_PC_screen ; Full screen
- rep movsw ; Blast out the screen
- pop es ; Get back original es
- pop ds ; and ds
-
- jmp SHORT PSC_Position ; Go set position and finish up
-
- PUBLIC PSC_Color
-
- PSC_Color:
- call Build_update_list ; First build an update list of locations
- ; to be changed, updating Old_Image as we go
-
- mov ax, Number_of_update_items ; See how many there are to do
- or ax, ax ; Are there any?
- jnz PSC_Update ; Yes, go do them
-
- PSC_Position:
- mov dx, Cursor ; Get current cursor pos
- mov ah, 2 ; Code to set cursor position
- mov bh, Which_page ; The current page
- int Screen ; Set cursor position
-
- jmp SHORT PSC_Done ; Go finish up
-
- PSC_Update:
- call Update_nondisplayed_page ; Run the update list against the
- ; page the user can't see
-
- mov dx, Cursor ; Get current cursor pos
- mov ah, 2 ; Code to set cursor position
- mov bh, 1 ; Get a 1
- sub bh, Which_page ; Minus current page number = other page
- int Screen ; Set cursor position
-
- call Switch_video_pages ; Then switch pages ...
-
- call Update_nondisplayed_page ; Then run the update list against the
- ; page we were just on
- mov dx, Cursor ; Get current cursor pos
- mov ah, 2 ; Code to set cursor position
- mov bh, 1 ; Get a 1
- sub bh, Which_page ; Minus current page number = other page
- int Screen ; Set cursor position
-
- call Switch_video_pages ; Then switch pages ...
-
- PSC_Done:
- and Screen_flags, NOT ( Changed + Force_screen_update )
- ; Screen + position are all set
-
- ret ; Go home
-
- PUBLIC Build_update_list
-
- Build_update_list:
- mov si, OFFSET Old_Image ; Ptr to old image
- mov di, Image_ptr ; Ptr to new image
- mov cx, Number_of_chars_on_PC_screen ; The number of words to compare
- sub bx, bx ; Clear count of update items
-
- test Screen_flags, Force_screen_update ; Want to do all locations?
-
- mov ax, Alloc_ds ; Pick up ptr to allocated segment
- mov ds, ax ; Make ds point to it
- ASSUME ds:Alloc
-
- jz BUL_Top ; No, go do it minimally
-
- BUL_Zap:
- add si, 2 ; Bump the pointers
- add di, 2
- call BUL_Do_difference ; Do the next character
-
- dec cx ; Decr counter
- jcxz BUL_Bot ; No more to do
-
- jmp BUL_Zap ; Go update the next character
-
- BUL_Top: repe cmpsw ; Are the old and new words the same?
- je BUL_Bot ; This batch was all equal, done here
-
- call BUL_Do_difference ; Deal with the difference
-
- jcxz BUL_Bot ; If no more to do, stop now
-
- jmp BUL_Top ; Go check the next pair of locations
-
- ; Hit a difference, deal with it
-
- BUL_Do_difference:
- mov dx, si ; Copy source offset to dx
- mov ax, 2 + OFFSET Old_Image ; Pick up addr of buffer plus 2
- sub dx, ax ; Get distance from start of buffer
- mov Update_list[bx], dx ; Store offset ptr in update list
- mov ax, es:-2[di] ; Pick up the new display value
- mov Update_list + 2[bx], ax ; Store it in the update list
- mov -2[si], ax ; Store it in the old image screen too
- add bx, 4 ; Move to next item
- ret ; Done here
-
- BUL_Bot:
- mov ax, Datas_ds ; Pick up ptr to normal segment
- mov ds, ax ; Make ds point to it
- ASSUME ds:Datas
-
- shr bx, 1 ; Convert bytes to items
- shr bx, 1 ; (divide by four)
- mov Number_of_update_items, bx ; Store the updated count of items
- ret ; Done here
-
-
- PUBLIC Update_nondisplayed_page
-
- Update_nondisplayed_page:
- push es ; Save es
- push WORD PTR Number_of_update_items ; Save count of items
- mov bl, 1 ; Get a one
- sub bl, Which_page ; Get number of page we ARE NOT on
- sub bh, bh ; Zero top half of word
- shl bx, 1 ; Double for word offset
- mov ax, Video_page_addresses[bx] ; Pick up address of screen memory
- mov es, ax ; Set es to point to the screen buffer
- mov bx, OFFSET Update_list ; Get ptr to update list
- mov cx, Number_of_update_items ; Get count of items to update
- mov dx, CRT_status_port ; Pick up status port number
-
- mov ax, Alloc_ds ; Pick up ptr to allocated segment
- mov ds, ax ; Install it in ds
- ASSUME ds:Alloc
-
- mov di, [bx] ; Get next address to update
- mov bp, 2[bx] ; Get value to store
-
- UNP_1: in al, dx ; Get status
- shr al, 1 ; Shift lower order bit into carry flag
- jc UNP_1 ; In retrace, wait until not retrace
-
- cli ; Ints off for this next loop
-
- UNP_2: in al, dx ; Get status
- shr al, 1 ; Shift lower order bit into carry flag
- jnc UNP_2 ; Not in retrace, wait until we are
-
- ; This update is for a single item, takes place during horizontal retrace
-
- xchg ax, bp ; Get back the char we need, save CRT flags
- stosw ; Store the new value
- sti ; Ints back on now
- add bx, 4 ; Move on to next item in list
- mov di, [bx] ; Get next address to update
-
- in al, dx ; Get status again
- test al, Vertical_retrace ; Test vertical retrace bit
- jnz UNP_Setup ; If in vertical retrace, take advantage of it
-
- mov bp, 2[bx] ; Get value to store
- loop UNP_1 ; Go do the next
-
- jmp SHORT UNP_Done ; Did them all, go finish up
-
- UNP_Setup:
- mov ax, 2[bx] ; Get value to store
- dec cx ; Decr to account for char we just did
- mov Number_of_update_items, cx ; First store the current count
-
- cmp cx, Max_number_of_items ; Too many?
- jle UNP_Ok ; No, this count is ok
-
- mov cx, Max_number_of_items ; Load up the maximum
-
- UNP_Ok: sub Number_of_update_items, cx ; Back off count by this many
-
- PUBLIC UNP_Inner
-
- ; This update is for a group of items, takes place during vertical retrace
-
- UNP_Inner:
- stosw ; Store the new value
- add bx, 4 ; Move on to next item in list
- mov di, [bx] ; Get next address to update
- mov ax, 2[bx] ; Get value to store
- loop UNP_Inner ; Go do the next
-
- mov bp, ax ; Save the char for later
- mov cx, Number_of_update_items ; Get number of items remaining
- or cx, cx ; Any left?
- jnz UNP_1 ; Still some left, go do them
-
- UNP_Done:
- mov ax, Datas_ds ; Ptr to normal data segment
- mov ds, ax ; Reinstall as ds
- ASSUME ds:Datas
-
- pop WORD PTR Number_of_update_items ; Get back count of item list
- pop es ; Get back saved es
- ret ; Done here
-
- ASSUME es:Datas
-
- Put_Screen ENDP
-
-
- ; Force all modes to be 80 by 25 text modes on IBM Color Graphics Adapter
-
- PUBLIC Enter_text_mode, Mode_Change_Table
-
- Enter_text_mode:
- mov ah, 15 ; Code to get current video mode
- int Screen ; Check it out
-
- cmp al, 10h ; Too high?
- ja ETM_Mode_ok ; Yeah, ignore it
-
- mov dh, al ; Save for a minute
- mov bx, OFFSET Mode_change_table ; Address of translation table
- xlat ; Change modes
- cmp dh, al ; Different?
- je ETM_Mode_ok ; Same thing, don't blink display
-
- push ax ; Save reg
- call Blank_current_page ; Clear out the graphic page
- pop ax ; Restore reg
-
- mov ah, 0 ; Code to set mode
- int Screen ; Set it up
-
- call Blank_current_page ; Clear out the text page
-
- ETM_Mode_ok:
- ret ; Done here
-
- PUBLIC Set_pointers
-
- Set_pointers PROC
-
- mov al, Row ; Pick up current row number
- mov bl, 2*Number_of_columns ; Size of a line
- mul bl ; Multiply it out
- add ax, OFFSET Screen_Image ; Add address of buffer
- mov Line_Ptr, ax ; Store line pointer
-
- mov bl, Column ; Pick up current column number
- sub bh, bh ; Clear high order half of word
- shl bx, 1 ; Shift left by 1 to double
- add ax, bx ; Add in the column offset
- mov Char_Ptr, ax ; Store character pointer
-
- or Screen_flags, Position_changed ; Flag screen change
- ret ; Done here
-
- Set_pointers ENDP
-
-
- ; Reset_esc_seq_reading -- Used to reset reading of Escape sequence
-
- Reset_esc_seq_reading PROC
-
- call Flush_esc_buffer ; First erase old escape buffer
- mov al, Esc ; Get an escape
- jmp Store_char_in_esc_buffer ; Store it as the start of a new esc seq
-
- Reset_esc_seq_reading ENDP
-
-
- ; Send_str_to_port -- Send a string to the port
-
- ; call with
- ; si/ ptr to string to send, zero terminated (ASCIZ)
-
- Send_str_to_port PROC
-
- cld ; Forwards
- lodsb ; Get a char from the string
- or al, al ; Equal to zero?
- je SSTP_1 ; Yes, quit on a null
-
- push si ; Save just in case
- call Send_char_to_port ; Send this char to the port
- pop si ; Get back saved ptr
-
- jmp Send_str_to_port ; Go try for another char
-
- SSTP_1: ret ; Hit null, done
-
- Send_str_to_port ENDP
-
-
- ; Send a different string depending on some flag
-
- Send_depending PROC
-
- If_cursor_keys_mode_set:
- test VT100_status_flags, Cursor_keys_mode ; See which way it is
- jz Leave_alone ; Normal, done here
-
- inc dx
- inc dx ; Bump twice
- jmp SHORT Leave_alone ; Go finish up
-
-
- If_keypad_application_mode_set:
-
- ; First, see if we are in NUM LOCK or ARROW KEY state ...
-
- push ax ; Save ax
- mov ah, 2
- int Kb ; Get current shift state
-
- mov bl, al ; Copy to bl
- and bl, NUM_State ; Mask out all but NUM_State
- mov cl, 4 ; This many
- shr bl, cl ; Shift NUM_State into Shift state's position
- xor bl, al ; Keep a 1 if states are different
- pop ax ; Restore saved reg
-
- test bl, Left_Shift ; Are we effectively in NUM_State?
- jnz IFK_NUM_State ; We are effectively in NUM_State, go do it
-
- ; In arrow key state, either beep or dispatch an arrow key
-
- mov bx, OFFSET Key_actions_2 ; Action table
- mov cx, Number_of_key_codes_2 ; Number of entries to check
- mov dx, OFFSET Key_codes_2 ; Scan code table to use
- mov di, dx ; Copy over addr of table
- cld ; Forwards
- repne scasw ; Search for word in table
-
- je IFK_Got_it ; Keep going if we found the key
-
- jmp Boop ; Else, just beep to say "meaningless key"
-
- IFK_Got_it:
- mov cx, di ; Copy to cx
- dec cx ; Drop by one word due to REPNE overshoot
- dec cx ; ...
- sub cx, dx ; Get index of char
- add bx, cx ; Add displacement to base of action table
- add bx, cx ; Double the offset
- add bx, cx ; Triple it (6 bytes instead of 2)
- lea dx, 2[bx] ; Get 2 + <addr of <addr of routine>> into dx
- jmp WORD PTR [bx] ; Dispatch to the desired routine
-
- IFK_NUM_State:
- test VT100_status_flags, Keypad_application_mode ; See which way it is
- jz Leave_alone ; Normal, done here
-
- inc dx
- inc dx ; Bump twice
-
- Leave_alone:
- mov bx, dx ; Copy to bx
- mov si, [bx] ; Pick up the proper pointer
- jmp Send_str_to_port ; Ship the string out to the port
-
- ; User hit ALT F7, first set flag for program exit, then ...
-
- Leave_program:
- call Exit2 ; Set exit flag
- nop
- nop
- nop
-
- ; User hit F5 or ALT F5, set flag to say we are leaving the emulator ...
-
- Leave_emulator:
-
- mov Quit_emulator, 1 ; Set flag to 1
- ret ; Done here
-
- ; User hit F6, call the Helper module
-
- Call_Helper:
-
- call Go_to_page_zero ; Be on page zero in display memory
-
- mov dx, Cursor_position ; Get current cursor pos
- mov ah, 2 ; Code to set cursor position
- mov bh, Which_page ; The current page
- int Screen ; Set cursor position
-
- call Helper ; Call the help module
-
- or Screen_flags, Changed ; Mark that screen needs help
- call Do_our_screen ; Update screen
-
- mov dx, Cursor_position ; Get current cursor pos
- mov ah, 2 ; Code to set cursor position
- mov bh, Which_page ; The current page
- int Screen ; Set cursor position
-
- ret ; Done here
-
- Send_depending ENDP
-
-
- ;***************************************************************************
-
- ; *Utilities for decoding VT100 Esc sequences and acting on them
-
- VT100_Utilities PROC
-
- ; Stolen from BIOS ...
-
- Beep: mov al, 10110110b ; timer initialization
- out timer + 3, al
- mov ax, beldiv ; Bell divisor
- out timer + 2, al
- mov al, ah
- out timer + 2, al ; output divisor
- in al, bel_prt
- mov ah, al ; remember original value
- or al, 3 ; turn speaker on
- out bel_prt, al
- mov cx, 8888h
- outbe1: loop outbe1 ; wait a while
- mov al, ah
- out bel_prt, al ; turn bell off
- ret ; and return
-
-
- ; Same thing, but a lower note ...
-
- PUBLIC Boop
-
- Boop: mov ax, beldiv ; Pick up current value
- push ax ; Save it
- shl ax, 1 ; Slide value left
- mov beldiv, ax ; Store it in beldiv
- call Beep ; Use the other routine
- pop WORD PTR beldiv ; Get back the saved value
- ret
-
-
- ; Restart escape sequence processing (hit new Esc)
-
- Restart_esc_seq_processing:
- call Reset_esc_seq_reading ; Reset this guy ...
- jmp Do_Escape ; Done with this one, start a new Esc seq
-
-
- ; Here to add a character to the current line at the current position in
- ; the current rendition (as set up in Attribute_byte) ... Advances
- ; Column and Char_Ptr unless in rightmost column, in which case the
- ; character is added but the position is not changed.
- ;
- ; call with
- ; al/ character to be added
-
- PUBLIC Add_this_char
-
- Add_this_char:
- call Do_Graphic_Char ; If we are in graphic mode, substitute
- ; proper graphic character for this one
-
- push ax ; Save reg
- mov ax, Alloc_ds ; Make es point to
- mov es, ax ; the allocated segment
- ASSUME es:Alloc
- pop ax ; Restore reg
- mov bx, Char_Ptr ; Ptr to char
- mov es:[bx], al ; Store the char
- inc bx ; Move to attr
- mov ah, Attribute_Byte ; Current attr
- mov es:[bx], ah ; Store it too
- inc bx ; Bump ptr over it
- mov ax, Datas_ds ; Make es point to
- mov es, ax ; the normal segment
- ASSUME es:Datas
-
- mov al, Column ; Current column
- cmp al, Highest_column ; In last column already?
- jne New_column ; No, go update ptrs
-
-
- ; We were in the rightmost column, and we just wrote a character ...
- ; So, if we are in AutoWrap mode then we now need to do a CrLf
-
- cmp AutoWrap, 0 ; In AutoWrap mode?
- jz Say_changed ; No, leave alone
-
- mov Column, 0 ; Simulate a Cr, the column is now zero
- mov ax, Line_Ptr ; Get line ptr
- mov Char_Ptr, ax ; Store as new char ptr
- call Move_down_scroll_up ; Call the linefeed routine
- jmp SHORT Say_changed ; Go finish up
-
- New_column:
- mov Char_Ptr, bx ; All ok, store new char ptr
- inc Column ; Bump column number too, fall through to ...
-
-
- ; Say that screen has changed, then return
-
- Say_changed:
- or Screen_flags, Screen_changed ; Flag screen change
- ret ; Done here
-
-
- ; If the Graphi bit is on in our rendition, and the character is in the
- ; graphic character range, then substitute the PC's closest graphic ...
-
- Do_Graphic_Char:
- test Rendition, Graphi ; Are we in graphics mode?
- jz DGC_done ; No
-
- cmp al, 95 ; Check bottom of range
- jb DGC_done ; Too low to worry about
-
- cmp al, 126 ; Check top of range
- ja DGC_done ; Too high to worry about
-
- sub al, 95 ; Pull character into range
- mov bx, OFFSET Graphic_translation_table ; Addr of table to use
- xlat Graphic_translation_table ; Translate char into graphic
-
- DGC_done:
- ret ; Done here
-
-
- ; Set new Tty graphic bit based on Char_set, G0_set and G1_set
-
- NewAtr: mov al, NOT Graphi ; Get graphic bit
- and Rendition, al ; Turn off bit for starters
-
- mov al, G0_set ; Assume set zero
- mov ah, Char_set ; Get which set we are in
- cmp ah, 0 ; Set 0?
- je Nw_1 ; Yes ...
-
- mov al, G1_set ; No, use set one
-
- Nw_1:
- or Rendition, al ; Set the bit accordingly
- ret ; and return
-
-
- ; Move_down_scroll_up -- Go to or create a new line, moving downwards
-
- PUBLIC Move_down_scroll_up
-
- Move_down_scroll_up:
- mov al, Row ; Which row we are on
- cmp al, Bottom_margin ; Are we on the bottom of the scrolling reg?
- je MDSU_2 ; Yes, go deal with the scroll
-
- cmp al, Highest_row ; Not bottom of scr reg, bot of screen?
- je MDSU_1 ; Yes, go deal with non-case
-
- inc Row ; Bump row number
- jmp Set_pointers ; Get new ptrs, then done here
-
- MDSU_1: ret ; Sequence to move down, can't ...
-
- ; Scroll region up by one line ...
-
- MDSU_2: mov bl, Number_of_columns * 2 ; Number of bytes in a column
- mov al, bl ; Create a working copy
- mul Top_margin ; Multiply by row number of top margin
- add ax, OFFSET Screen_image ; Address screen
- mov di, ax ; Install as destination
-
- sub bh, bh ; Clear high half of word
- add ax, bx ; Add in another line's worth
- mov si, ax ; Install as source
-
- mov al, Bottom_margin ; Start with bottom margin row number
- sub al, Top_margin ; Number of lines to move
- mul bl ; Multiply by number of bytes in a row
- shr ax, 1 ; Convert to number of words
- mov cx, ax ; Install as repeat count
-
- mov ax, Alloc_ds ; Set up ptrs to allocated segment in
- mov ds, ax ; ds and
- mov es, ax ; es
- ASSUME ds:Alloc, es:Alloc
-
- cld ; Move forwards as we copy
- rep movsw ; Scroll the region up by one row
-
- mov cx, Number_of_columns ; Number of words in a row
- mov ax, 0720h ; Normal spaces
- rep stosw ; Fill the new line with blanks
-
- mov ax, Datas_ds ; Return segment ptrs to normal
- mov ds, ax
- mov es, ax
- ASSUME ds:Datas, es:Datas
-
- inc Number_of_scrolls_done ; Keep track for early quit
- or Screen_flags, Screen_changed ; Flag screen change
- ret ; Done here
-
-
- ; Move_up_scroll_down -- Go to or create a new line, moving upwards
-
- PUBLIC Move_up_scroll_down
-
- Move_up_scroll_down:
- mov al, Row ; The row we are on
- cmp al, Top_margin ; Are we in the top row of the scrolling reg?
- je MUSD_2 ; Yes, go deal with the scroll
-
- or al, al ; Already as high as we can go?
- jz MUSD_1 ; Yes, go deal with non-case
-
- dec Row ; Bump row number
- jmp Set_pointers ; Get new ptrs, then done here
-
- MUSD_1: ret ; Sequence to move up, can't ...
-
- ; Scroll region down by one line ...
-
- MUSD_2: mov bl, Number_of_columns * 2 ; Number of bytes in a column
- mov al, bl ; Create a working copy
- mul Bottom_margin ; Multiply by row number of bottom margin
- add ax, OFFSET Screen_image + (Highest_column * 2)
- ; Address last word in the line
- mov di, ax ; Install as destination
-
- sub bh, bh ; Clear high half of word
- sub ax, bx ; Subtract out another line's worth
- mov si, ax ; Install as source
-
- mov al, Bottom_margin ; Start with bottom margin row number
- sub al, Top_margin ; Number of lines to move
- mul bl ; Multiply by number of bytes in a row
- shr ax, 1 ; Convert to number of words
- mov cx, ax ; Install as repeat count
-
- mov ax, Alloc_ds ; Set up ptrs to allocated segment in
- mov ds, ax ; ds and
- mov es, ax ; es
- ASSUME ds:Alloc, es:Alloc
-
- std ; Move backwards as we copy
- rep movsw ; Scroll the region down by one row
-
- mov cx, Number_of_columns ; Number of words in a row
- mov ax, 0720h ; Normal spaces
- rep stosw ; Fill the new line with blanks
-
- mov ax, Datas_ds ; Return segment ptrs to normal
- mov ds, ax
- mov es, ax
- ASSUME ds:Datas, es:Datas
-
- inc Number_of_scrolls_done ; Keep track for early quit
- or Screen_flags, Screen_changed ; Flag screen change
- ret ; Done here
-
-
- ; Return skip ...
-
- RSkp PROC
-
- pop bx ; Pick up return address
- add bx, 3 ; Bump up by 3
- push bx ; Back on the stack
- ret ; Then just return ...
-
- RSkp ENDP
-
-
- ; Set attribute byte based on rendition
-
- PUBLIC Set_attribute_byte
-
- Set_attribute_byte:
- mov al, Rendition ; Load the current VT100 graphic rendition
- and al, Bold+Underscored+Blinking+Inverted ; Keep only these bits
- mov bx, OFFSET Color_attributes ; Addr of rend-to-attribute table
- xlat Color_attributes ; Translate rendition to attribute
- mov Attribute_byte, al ; Set up attribute
- ret ; Done here
-
-
- ; call PullCh
- ; Used to get the backed-up char, if any, or a character from the
- ; escape buffer, if any, else from the port, if any ... returns skip
- ; if a character was found ...
- ;
- ; Returns ...
- ; +1 if no char to be found
- ; +2 if found a char (from either buffer), char is in al
-
- PUBLIC PullCh
-
- PullCh PROC
-
- mov al, Backed_up_char ; Get the backed-up char
- cmp al, 0 ; Did we get one?
- je PCH_1 ; No, get a new char
-
- mov Backed_up_char, 0 ; Clear char for next time
- RetSkp ; Go RetSkp
-
- PCH_1: mov bx, EBufGt ; Escape buf getter ptr
- cmp bx, EBufPt ; Compare with putter ptr
- je PCH_2 ; If same, no chars held there
-
- mov al, [bx] ; Pick up the char
- inc EBufGt ; Bump the ptr
- jmp SHORT PCH_End ; Go finish up
-
- PCH_2: call Get_char_from_port ; See if another char is available
- jnc PCH_Ret ; If no char, just return
-
- ; We just got a char from the host, so if we are running under control of a
- ; script we need to let the script processor know what that character is.
-
- cmp Script_processor, 0 ; Is there a script processor to run?
- je PCH_No_script ; No
-
- mov ah, 1 ; Code for "character" entry
- call Script_processor ; Let it do its thing
-
- PCH_No_script:
- test flags, capt ; capturing output?
- jz PCH_4 ; no, forget this part
-
- push ax ; save char
- call captrtn ; give it captured character
- pop ax ; restore character and keep going
-
- PCH_4: or al, al ; Is the char a null?
- jz PCH_2 ; Got a null, go try again
-
- cmp al, DEL ; Or delete?
- je PCH_2 ; Yes, ignore this char and try again
-
- cmp al, 'X'-100q ; Control-X?
- je PCH_Abort ; Yes, blow out esc seq
-
- cmp al, 'Z'-100q ; Control-Z?
- je PCH_Abort ; Yes, blow out esc seq
-
- call Store_char_in_esc_buffer ; Store the char in the escape buffer
-
- PCH_End:
- mov Previous_char, al ; Save the char
- RetSkp ; Return with the char
-
- PCH_Abort:
- mov al, 177 ; Char decimal 177 is the IBM display char
- ; most closely corresponding to VT100's
- ; error blot ... half dots on ...
- call Add_this_char ; Write the character to the screen
- jmp Abort_esc_sequence ; ^X and ^Z will halt any esc sequence ...
-
- PCH_Ret: ret ; No char to get, just return
-
- PullCh ENDP
-
-
- ; call Store_char_in_esc_buffer
- ; Store a new character in the escape buffer for later rereading
-
- PUBLIC Store_char_in_esc_buffer
-
- Store_char_in_esc_buffer PROC
-
- mov ah, EBufCt ; Pick up count of chars so far
- cmp ah, EBufLn-1 ; Is the buffer full?
- jge Stc_E ; Full, give up
-
- mov di, EBufPt ; Get putter ptr
- cld ; Forwards
- stosb ; Store char in buffer
- mov EBufPt, di ; Store updated putter ptr
- mov EBufGt, di ; Store as getter ptr also to prevent rereading
- inc EBufCt ; Bump count of chars in buffer
-
- Stc_E: ret
-
- Store_char_in_esc_buffer ENDP
-
-
- ; call UnPull
- ; Used to back up the pull sequence by one character
-
- UnPull PROC
-
- mov al, Previous_char ; Pick up the last char
- mov Backed_up_char, al ; Save it as the backed-up char
- ret ; and return
-
- UnPull ENDP
-
-
- ; PulNum -- Use PullCh to read a number
-
- ; call PulNum
- ; Used to read in a number using PullCh
-
- ; Returns ...
- ; +1 if hit eof on call to PullCh
- ; +2 if got a number, number in dl
-
- PUBLIC PulNum
-
- PulNum: sub dl, dl ; First clear dl
-
- PN_1: call PullCh ; Get a char
- RetNop ; No
-
- cmp al, '0' ; Lower than 0?
- jl PN_2 ; Yes, done here
-
- cmp al, '9' ; Higher than 9?
- jg PN_2 ; Yes, done here
-
- sub al, '0' ; Make ASCII digit into decimal
- xchg al, dl ; Swap al and dl
- mov bl, 10 ; Get a ten
- mul bl ; Multiply old number by ten
- add dl, al ; Add in the new digit
- jmp PN_1 ; Go get another char
-
- PN_2: call UnPull ; Release the char we just read
- RetSkp ; Tell caller he has a number
-
-
- ; Get_numeric_params -- Get Vt100 Escape sequence numbers ...
-
- PUBLIC Get_numeric_params
-
- Get_numeric_params:
- sub ax, ax ; Get a zero
- mov NumCnt, al ; Clear count
- mov NumPtr, al ; and ptr
-
- GNP_1: call PulNum ; Try to get a number
- RetNop ; No
-
- call PullCh ; Get the number's terminating char
- RetNop ; No
-
- inc NumCnt ; Bump count of args
- mov bl, NumCnt ; Copy to bx
- sub bh, bh ; Clear high half
- mov Nums-1[bx], dl ; Store the number we got from PulNum
-
- cmp al, ';' ; Was terminator a semi-colon?
- je GNP_1 ; Yes, go get another argument ...
-
- call UnPull ; Un-get char so the other routine can get it
- RetSkp ; and return nicely ...
-
-
- ; Get_next_number -- Get a single number from previously stored numbers
-
- PUBLIC Get_next_number
-
- Get_next_number:
- inc NumPtr ; Bump ptr
- mov bl, NumPtr ; Get ptr into low half
- cmp bl, NumCnt ; Off end of list?
- jle GNN_1 ; No, keep going
-
- ret ; No more, done here
-
- GNN_1: sub bh, bh ; Zero high half
- mov al, Nums-1[bx] ; Get the next number
- RetSkp ; Tell caller he has a number ...
-
-
- ; Get a single numeric parameter, default is zero if no parameters.
-
- PUBLIC Default_zero
-
- Default_zero:
- call Get_next_number ; Pick up next arg, if any
- jmp SHORT D0_1 ; No more, go take default
- nop ; 3 bytes ...
-
- ret ; Got one, use it
-
- D0_1: sub al, al ; Default to 0
- ret ; Done here
-
-
- ; Get a single numeric parameter, default is one (if param is zero
- ; or if there is no parameter).
-
- PUBLIC Default_one
-
- Default_one:
- call Get_next_number ; Pick up next arg, if any
- jmp SHORT D1_1 ; No more, go take default
- nop ; 3 bytes ...
-
- or al, al ; Is it zero?
- jnz D1_2 ; No, go use it
-
- D1_1: mov al, 1 ; Default to 1
-
- D1_2: ret ; Done here
-
-
- ; Set up to run a script processor at selected times, or clear it with zero
-
- Set_up_script_processor_PC:
-
- mov Script_Processor, ax ; Set this up, or zero it out
- ret ; That was easy
-
-
- ; Convert an integer into its decimal ASCII representation in memory
-
- ; Call with
- ; ax/ number to be converted
- ; di/ ptr to area to write the string
-
- Nout: sub dx, dx ; Make a zero
- mov bx, 10 ; Get a ten
- div bx ; Divide ax by ten
- push dx ; Save remainder
- or ax, ax ; Quotient zero?
- jz Nout_1 ; Yes, don't dig deeper
-
- call Nout ; Recursively get the rest of the number
-
- Nout_1: pop ax ; Get back saved digit
- add al, '0' ; Convert this digit
- stosb ; Put it into the output area
- ret ; Done at this level
-
- VT100_Utilities ENDP
-
-
- ;******************************************************************************
-
- ; *Character handling routines ...
-
- ; Some control characters ...
-
- Ctrl_Ch PROC
-
-
- ; Bell
-
- Do_Bell:
- call Beep ; Beep the bell
- jmp Done_with_char
-
-
- ; Tab
-
- Do_Tab: mov al, Column ; Get current column #
- or al, 7 ; Go to next tab stop
- inc al ; Fancy trick ...
- cmp al, Highest_column ; Too high?
- jle Dot_2 ; No
-
- mov al, Highest_column ; Truncate to width ...
-
- Dot_2: mov Column, al ; Save new column number
- jmp Set_ptrs_then_done
-
-
- ; Backspace
-
- Do_Bs: dec Column ; Decr the column
- jns Dob_1 ; Is it now negative?
-
- mov Column, 0 ; Set col to zero
-
- Dob_1: jmp Set_ptrs_then_done ; Set up new pointers
-
-
- ; Carriage return
-
- Do_Cr: mov Column, 0 ; Column is now zero
- mov ax, Line_Ptr ; Get line ptr
- mov Char_Ptr, ax ; Store as new char ptr
- or Screen_flags, Position_changed ; Flag screen change
- jmp Done_with_char
-
-
- ; Shift out
-
- Do_SO: mov al, 1 ; Get a one
- jmp SHORT DoSI_1 ; Join common code
-
-
- ; Shift in
-
- Do_SI: sub al, al ; Clear al
- DoSI_1: mov Char_set, al ; Put us in the G0 charset
- call NewAtr ; Go set up a new attr based on this
- jmp Done_with_char
-
- Ctrl_Ch ENDP
-
-
- ; Escape ...
-
- PUBLIC Do_escape
-
- Do_Escape PROC
-
- call PullCh ; Try to get a char
- jmp No_more_chars ; No more chars, try again later
-
- mov bx, OFFSET ActTb2 ; Action table
- mov cx, NChrTb2 ; Number of chars to check
- mov dx, OFFSET ChrTb2 ; The character table
- jmp Check_Table ; Go dispatch to the right routine
-
- Do_Escape ENDP
-
-
- ; Hit Escape left square bracket ($[), keep checking ...
-
- PUBLIC Do_left_square
-
- Do_left_square PROC
-
- call PullCh ; Look at the next char
- jmp No_more_chars ; No more chars, try again later
-
- or VT100_status_flags, Private_esc_seq ; Assume private esc sequence
-
- cmp al, '?' ; Hit qmark?
- je DSQ_1 ; Yes, "eat" it
-
- call UnPull ; Not qmark, get it back for Get_numeric_params
- and VT100_status_flags, NOT Private_esc_seq ; Not private esc sequence
-
- DSQ_1: call Get_numeric_params ; Get numeric parameters, if any
- jmp No_more_chars ; Bomb
-
- call PullCh ; Get the closing char of the sequence
- jmp No_more_chars ; No more chars, try again later
-
- test VT100_status_flags, Printer_controller_mode
- jz DSQ_2 ; Not in funny mode, continue as usual
-
- cmp al, 'i' ; Only seq that gets us out of funny mode ..
- je DSQ_2 ; That's it, go run with it
-
- jmp Done_with_char ; In funny mode, not seq to leave it, ignore
-
- DSQ_2: mov bx, OFFSET ActTb3 ; Action table
- mov cx, NChrTb3 ; Number of chars to check
- mov dx, OFFSET ChrTb3 ; The character table
- jmp Check_Table ; Go dispatch to the right routine
-
- Do_left_square ENDP
-
-
- ; Saw Escape left paren ...
-
- Do_left_paren PROC
-
- call PullCh ; Get next char
- jmp No_more_chars ; No more chars, try again later
-
- test VT100_status_flags, Printer_controller_mode
- jz LFP_1 ; Not in funny mode, continue as usual
-
- jmp Done_with_char ; In funny mode, not seq to leave it, ignore
-
- LFP_1: mov bx, OFFSET ActTb4 ; Action table
- mov cx, NChrTb4 ; Number of chars to check
- mov dx, OFFSET ChrTb4 ; The character table
- jmp Check_Table ; Go dispatch to the right routine
-
- Lfp_B: sub al, al ; Get a zero
- jmp SHORT Lfp_Mr ; Join common code
-
- Lfp_0: mov al, Graphi ; Get graphic bit
-
- Lfp_Mr: mov G0_set, al ; Set G0 charset to whatever
- call NewAtr ; Set it up
- jmp Done_with_char
-
- Do_left_paren ENDP
-
-
- ; Saw Escape right paren ...
-
- Do_right_paren PROC
-
- call PullCh ; Get next char
- jmp No_more_chars ; No more chars, try again later
-
- test VT100_status_flags, Printer_controller_mode
- jz RTP_1 ; Not in funny mode, continue as usual
-
- jmp Done_with_char ; In funny mode, not seq to leave it, ignore
-
- RTP_1: mov bx, OFFSET ActTb5 ; Action table
- mov cx, NChrTb5 ; Number of chars to check
- mov dx, OFFSET ChrTb5 ; The character table
- jmp Check_Table ; Go dispatch to the right routine
-
- Rtp_B: sub al, al ; Get a zero
- jmp SHORT Rtp_Mr ; Join common code
-
- Rtp_0: mov al, Graphi ; Get graphic bit
-
- Rtp_Mr: mov G1_set, al ; Set G1 charset to whatever
- call NewAtr ; Set it up
- jmp Done_with_char
-
- Do_right_paren ENDP
-
-
- ; Saw Escape pound sign ...
-
- Do_pound_sign PROC
-
- call PullCh ; Get next char
- jmp No_more_chars ; No more chars, try again later
-
- cmp al, Esc ; Escape?
- je DOP_1 ; Yes, do the decent thing
-
- jmp Done_with_char ; These are all not supported yet ...
-
- DOP_1: jmp Restart_esc_seq_processing ; Go get a new escape sequence
-
- Do_pound_sign ENDP
-
-
- ;***************************************************************************
-
- ; *VT100 Escape Sequences as described in VT100 User Guide* ...
-
- VT100_Routines PROC
-
- ; Cursor Backward
-
- CUB: call Default_one ; Get argument, default to one
-
- mov ah, Column ; Get current column
- sub ah, al ; Back it up by requested # columns
- jns CUB_1 ; Is it now negative?
-
- sub ah, ah ; Make a zero
-
- CUB_1: mov Column, ah ; Set column to new value
- jmp SHORT Set_ptrs_then_done
-
-
- ; Cursor Down
-
- CUD: call Default_one ; Pick up the arg, default to 1
-
- mov ah, Row ; Get current row
- add ah, al ; Add in requested # rows
- mov al, Highest_row ; Maximum offset for row number
- cmp ah, al ; Is new row number too high?
- jbe CUD_1 ; All is OK ...
-
- mov ah, al ; Use the maximum
-
- CUD_1: mov Row, ah ; Update the row
- jmp SHORT Set_ptrs_then_done
-
-
- ; Cursor Forward
-
- CUF: call Default_one ; Pick up the arg, default to 1
-
- mov ah, Column ; Get current column
- add ah, al ; Add in requested # columns
- mov al, Highest_column ; Maximum offset
- cmp ah, al ; Is new column number too high?
- jbe CUF_1 ; All is OK ...
-
- mov ah, al ; Use the maximum
-
- CUF_1: mov Column, ah ; Update the column
- jmp SHORT Set_ptrs_then_done
-
-
- ; Cursor Position
-
- PUBLIC CUP
-
- CUP: call Default_one ; Pick up the first arg, default to 1
- dec al ; Make it an offset
- jns CUP_1 ; Not negative, move on
-
- sub al, al ; Make it zero
-
- CUP_1: mov ah, Highest_row ; Maximum offset
- cmp al, ah ; Is requested row number too high?
- jbe CUP_2 ; In range, move on
-
- mov al, ah ; Use the maximum
-
- CUP_2: mov NewRow, al ; Save as new row number
-
- call Default_one ; Pick up the second arg, default to 1
- dec al ; Make it an offset
- jns CUP_3 ; Not negative, move on
-
- sub al, al ; Make it zero
-
- CUP_3: mov ah, Highest_column ; Maximum offset
- cmp al, ah ; Is requested column number too high?
- jbe CUP_4 ; In range, move on
-
- mov al, ah ; Use the maximum
-
- CUP_4: mov Column, al ; Save as new column number
-
- mov al, NewRow ; Load up the requested row number
- mov Row, al ; Store it
-
- jmp SHORT Set_ptrs_then_done
-
-
- ; Cursor Up
-
- CUU: call Default_one ; Get argument, default to one
-
- mov ah, Row ; Get current row
- sub ah, al ; Back it up by requested # rows
- jns CUU_1 ; Is it now negative?
-
- sub ah, ah ; Make a zero
-
- CUU_1: mov Row, ah ; Set row to new value
-
- ; Fall thru to Set_ptrs_then_done ...
-
- ; Common finish up point for cursor positioning routines
-
- Set_ptrs_then_done:
- call Set_pointers ; Set up new pointers
- jmp Done_with_char ; Then are are done
-
-
- ; Device Attributes
-
- DA: test VT100_status_flags, Private_esc_seq ; Include a "?" ?
- jnz DA_ignore ; Yes, don't answer it
-
- call Default_zero ; Get parameter, if any
-
- or al, al ; Is it zero?
- jnz DA_ignore ; No, just ignore it
-
- mov si, OFFSET DA_Str ; What to send ...
- call Send_str_to_port ; Send the string to the port
-
- DA_ignore:
- jmp Done_with_char
-
-
- ; DEC (private) terminal ID
-
- DECID: jmp DA ; Same thing
-
-
- ; DEC (private) Keypad Application Mode
-
- DECKPAM:
- or VT100_status_flags, Keypad_application_mode ; Turn on the flag
- jmp Done_with_char
-
-
- ; DEC (private) Keypad Numeric Mode
-
- DECKPNM:
- and VT100_status_flags, NOT Keypad_application_mode ; Turn off the flag
- jmp Done_with_char
-
-
- ; DEC (private) Load LEDs
-
- PUBLIC DECLL
-
- DECLL: call Default_zero ; Get the first parameter, default zero
-
- DECLL_Loop:
- cmp al, 4 ; Highest value we have code for
- jg DECLL_Ignore ; Can't handle it
-
- cbw ; Blow up to full word
- shl ax, 1 ; Double offset for words
- mov bx, ax ; Copy to bx
- jmp DECLL_Table[bx] ; Dispatch thru table to correct routine
-
- DECLL_0:
- mov al, NOT (LED1 + LED2 + LED3 + LED4)
- and LEDs, al ; Turn off those bits ...
- jmp SHORT DECLL_Ignore ; Done with this part
-
- DECLL_1:
- mov al, LED1 ; Flag for LED # 1
- jmp SHORT DECLL_Set ; Go set the bit
-
- DECLL_2:
- mov al, LED2 ; Flag for LED # 2
- jmp SHORT DECLL_Set ; Go set the bit
-
- DECLL_3:
- mov al, LED3 ; Flag for LED # 3
- jmp SHORT DECLL_Set ; Go set the bit
-
- DECLL_4:
- mov al, LED4 ; Flag for LED # 4
-
- DECLL_Set:
- or LEDs, al ; Set the bit
-
- DECLL_Ignore:
- call Get_next_number ; Try to get another number
- jmp SHORT DECLL_Done ; No such luck ...
- nop ; 3 bytes
-
- jmp DECLL_Loop ; Got one, go do something with it
-
- DECLL_Done:
- mov Prev_shift_state, 0FFh ; Force set up of new mode line
- jmp Done_with_char ; Done with this one
-
-
- ; DEC (private) Restore Cursor
-
- DECRC: mov al, Save_char_set ; Pick up which set we were in
- mov Char_set, al ; Restore it
-
- mov al, Save_G0_set ; Pick up saved char set
- mov G0_set, al ; Restore it
-
- mov al, Save_G1_set ; Pick up saved char set
- mov G1_set, al ; Restore it
-
- mov al, Save_rendition ; Pick up rendition
- mov Rendition, al ; Restore it
-
- mov ax, Save_position ; Pick up old cursor position
- mov Cursor_position, ax ; Restore it
-
- jmp Set_ptrs_then_done ; Get a new ptr to the line we are on, done
-
-
- ; DEC (private) Save Cursor
-
- DECSC: mov al, Char_set ; Pick this up
- mov Save_char_set, al ; Save it
-
- mov al, G0_set ; Pick this up
- mov Save_G0_set, al ; Save it
-
- mov al, G1_set ; Pick this up
- mov Save_G1_set, al ; Save it
-
- mov al, Rendition ; Pick this up
- mov Save_rendition, al ; Save it
-
- mov ax, Cursor_position ; Pick this up
- mov Save_position, ax ; Save it
-
- jmp Set_ptrs_then_done ; Get a new ptr to the line we are on, done
-
-
- ; DEC (private) Set Top and Bottom Margins
-
- PUBLIC DECSTBM
-
- DECSTBM:
- call Default_one ; Try to get the top margin, def is 1
-
- dec al ; Change to offset
- mov Top_margin, al ; Store it
-
- call Default_zero ; Try to get bottom margin, use zero for now
-
- or al, al ; Was it zero?
- jnz DST_1 ; No, use what we got
-
- mov al, Number_of_rows ; Default to number of rows on screen
-
- DST_1: dec al ; Change to offset
- mov Bottom_margin, al ; Store the margin we got
-
- ; This Esc sequence puts us in the home position ...
-
- sub ax, ax ; Get a zero
- mov Cursor_position, ax ; Move to upper left corner
- jmp Set_ptrs_then_done ; Set pointers, done with this char
-
-
- ; Device Status Report
-
- DSR: call Get_next_number ; Get a number
- jmp SHORT DSR_1 ; If no number, default to 5
- nop ; 3 bytes
-
- cmp al, 5 ; Is it five?
- jne DSR_2 ; No, see what it is
-
- DSR_1: mov si, OFFSET DSR_str ; Load up ptr to string we want to send
- call Send_str_to_port ; Send it
- jmp Done_with_char
-
- DSR_2: cmp al, 6 ; Is it six?
- jne DSR_End ; No, then don't know what to do anyway
-
- mov si, OFFSET CPR_str ; Load ptr to string
- call Send_str_to_port ; Send it
-
- mov al, Row ; Pick up row number
- cbw ; Convert to word
- inc ax ; Row and col numbers start at 1, not zero
- mov di, OFFSET LoWork ; Ptr to work area
- push di ; Save it
- call Nout ; Write number to work area
- sub al, al ; Make a zero
- stosb ; Tie off the string
- pop si ; Get back ptr into si
- call Send_str_to_port ; Send the string along
-
- mov al, ';' ; A semicolon
- call Send_char_to_port ; Type it
-
- mov al, Column ; Pick up column number
- cbw ; Convert to word
- inc ax ; Row and col numbers start at 1, not zero
- mov di, OFFSET LoWork ; Ptr to work area
- push di ; Save it
- call Nout ; Write number to work area
- sub al, al ; Make a zero
- stosb ; Tie off the string
- pop si ; Get back ptr into si
- call Send_str_to_port ; Send the string along
-
- mov al, 'R' ; A capital R
- call Send_char_to_port ; Send to port, return from there
-
- DSR_End: jmp Done_with_char ; Can't deal with it ...
-
-
- ; Erase in Display
-
- PUBLIC ED
-
- ED: call Default_zero ; Get a param
-
- cmp al, 17 ; Is it our "magic" value?
- je ED_Magic ; It is ...
-
- cmp al, 18 ; Code to identify ourselves (non-VT100)?
- je ED_Identify ; It is ...
-
- cmp al, 19 ; Code to quit to command mode?
- je ED_Command ; It is ...
-
- cmp al, 20 ; Code to quit to DOS?
- je ED_Exit_to_DOS ; It is ...
-
- cmp al, 21 ; Code to preload a command?
- je ED_Preload ; It is ...
-
- cmp al, 2 ; Is it too high?
- jg ED_ignore ; Yes ...
-
- cbw ; Blow up to full word
- shl ax, 1 ; Double offset for words
- mov bx, ax ; Copy to bx
- jmp ED_Table[bx] ; Dispatch thru table to correct routine
-
- ED_Magic:
- call Go_to_page_zero ; Go to base page
- call Enter_Server ; Jump suddenly into Server mode
- nop ; Skips on success
- nop
- nop
- call SerIni_PC ; In case port got turned off
- or Screen_flags, Force_screen_update ; Update the world
- call Do_our_screen ; Restore our screen
- jmp SHORT ED_ignore
-
- ED_Identify:
- mov si, OFFSET Ident_str ; What to send ...
- call Send_str_to_port ; Send the string to the port
- jmp SHORT ED_ignore
-
- ED_Command:
- call Leave_emulator
- jmp SHORT ED_ignore
-
- ED_Exit_to_DOS:
- call Leave_program
- jmp SHORT ED_ignore
-
- ED_Preload:
- sub cx, cx ; Zero characters preloaded so far
- mov di, OFFSET Preload_buffer ; Point at the start of our buffer
- cld ; Forwards
-
- ED_ploop:
- push di ; Save register just in case
-
- call PullCh ; Get a new character
- jmp ED_p_no_more ; No such luck
-
- pop di ; Restore register
-
- cmp al, Esc ; Hit an escape?
- je ED_pdone ; Hit the end, don't store Esc
- cmp cx, 100 ; Got too many chars?
- jae ED_pdone ; Don't take too many
-
- stosb ; Store char in our buffer
- inc cx ; Count the character
- mov Preload_flag, 0FFh ; Flag that there is a preloaded command
- jmp ED_ploop ; Do more
-
- ED_p_no_more:
- pop di ; Fix up stack
- jmp No_more_chars ; Try again later
-
- ED_pdone:
- sub al, al ; Make a zero
- stosb ; Tie off the string
-
- ED_ignore:
- jmp Done_with_char
-
- ED_0: mov cx, Number_of_chars_on_VT100_screen ; Start with this number
- mov al, Row ; Which row we are on
- mov bh, Number_of_columns ; Words per row
- mul bh ; Total number of words above us on screen
- mov bx, ax ; Copy to bx
- mov al, Column ; Current column
- cbw ; Make full word
- add ax, bx ; Total number of chars "above" us
- sub cx, ax ; Numbers of words still to clear
- mov di, Char_ptr ; Where to start clobbering
- cld ; Move forward
- jmp ED_z ; Go finish up ...
-
- ED_1: mov al, Row ; Which row we are on
- mov bh, Number_of_columns ; Words per row
- mul bh ; Total number of words above us on screen
- mov cx, ax ; Copy to cx
- mov al, Column ; Current column
- cbw ; Make full word
- inc ax ; Bump by one to include current position
- add cx, ax ; Total number of chars "above" us
- mov di, Char_ptr ; Where to start clobbering
- std ; Move backward
- jmp ED_z ; Go finish up ...
-
- ED_2: mov cx, Number_of_chars_on_VT100_screen ; Number of chars to lay down
- mov di, OFFSET Screen_Image ; Where to put them
- cld ; Move forward
-
- ED_z: mov ax, Alloc_ds ; Allocated segment
- mov es, ax ; Set up es
- ASSUME es:Alloc
-
- mov ax, 0720h ; Want normal spaces
- rep stosw ; Clear ...
-
- mov ax, Datas_ds ; Normal segment
- mov es, ax ; Set up es
- ASSUME es:Datas
-
- or Screen_flags, Screen_changed ; Flag screen change
- jmp ED_ignore
-
-
- ; Erase in Line
-
- PUBLIC EL
-
- EL: call Default_zero ; Get a param
-
- cmp al, 2 ; Is it too high?
- jg EL_ignore ; Yes ...
-
- cbw ; Blow up to full word
- shl ax, 1 ; Double offset for words
- mov bx, ax ; Copy to bx
- jmp EL_Table[bx] ; Dispatch thru table to correct routine
-
- EL_0: mov cx, Number_of_columns ; Start with this number
- mov al, Column ; Column number we are in
- cbw ; Make full word
- sub cx, ax ; Number of chars to our right
- mov di, Char_ptr ; Where to start clobbering
- cld ; Move forward
- jmp EL_z ; Go finish up ...
-
- EL_1: mov al, Column ; Which column we are in
- cbw ; Make full word
- inc ax ; Bump by one to include current position
- mov cx, ax ; Copy to cx
- mov di, Char_ptr ; Where to start clobbering
- std ; Move backward
- jmp EL_z ; Go finish up ...
-
- EL_2: mov cx, Number_of_columns ; Number of words to lay down
- mov di, Line_ptr ; Where to put the bytes
- cld ; Move forward
-
- EL_z: mov ax, Alloc_ds ; Allocated segment
- mov es, ax ; Set up es
- ASSUME es:Alloc
-
- mov ax, 0720h ; Get a space, normal attribute
- rep stosw ; Zap the buffer
-
- mov ax, Datas_ds ; Normal segment
- mov es, ax ; Set up es
- ASSUME es:Datas
-
- or Screen_flags, Screen_changed ; Flag screen change
-
- EL_ignore:
- jmp Done_with_char
-
-
- ; Horizontal and Vertical Position
-
- HVP: jmp CUP ; Same thing as cursor position
-
-
- ; Index
-
- IND: call Move_down_scroll_up ; Create a new line, the usual way ...
- jmp Done_with_char
-
-
- ; Media Copy
-
- PUBLIC MC
-
- MC: call Default_zero ; Get the first parameter, default is 0
-
- MC_Loop: or al, al ; See if negative
- js MC_Ignore ; Negative, ignore it
-
- cmp al, 5 ; Highest value we have code for
- jg MC_Ignore ; Can't handle it
-
- cbw ; Blow up to full word
- shl ax, 1 ; Double offset for words
- mov bx, ax ; Copy to bx
- jmp MC_Table[bx] ; Dispatch thru table to correct routine
-
- ; Print screen, not implemented
-
- MC_0: jmp SHORT MC_Ignore
-
- ; Print cursor line, not implemented
-
- MC_1: jmp SHORT MC_Ignore
-
- ; Printer controller off, or Auto print off
-
- MC_4: test VT100_status_flags, Private_esc_seq
- jz MC4_x ; Not private
-
- and VT100_status_flags, NOT Auto_copy_mode ; Turn it off
- jmp SHORT MC_Ignore
-
- MC4_x: and VT100_status_flags, NOT Printer_controller_mode ; Turn it off
- jmp SHORT MC_Ignore
-
- ; Printer controller on, or Auto print on
-
- MC_5: test VT100_status_flags, Private_esc_seq
- jz MC5_x ; Not private
-
- or VT100_status_flags, Auto_copy_mode ; Turn it on
- jmp SHORT MC_Ignore
-
- MC5_x: or VT100_status_flags, Printer_controller_mode ; Turn it on
-
- MC_Ignore: mov Prev_shift_state, 0FFh ; Force set up of new mode line
- jmp Done_with_char ; Done with this one
-
-
- ; Next Line
-
- NEL: mov Column, 0 ; Clear the column offset
- jmp IND ; Join common code
-
-
- ; Reverse Index
-
- RI: call Move_up_scroll_down ; Create a new line, the other way ...
- jmp Done_with_char
-
-
- ; Reset Mode
-
- PUBLIC RM
-
- RM: call Default_zero ; Get the first parameter, default is 0
-
- RM_1: cmp al, 1 ; One?
- jne RM_2 ; No
-
- and VT100_status_flags, NOT Cursor_keys_mode ; Turn off the bit
-
- RM_2: call Get_next_number ; Try to get another number
- jmp Done_with_char
-
- jmp RM_1 ; Got one, go do something with it
-
-
- ; Select Graphic Rendition
-
- PUBLIC SGR
-
- SGR: call Default_zero ; Get the first parameter, default zero
-
- SGR_Loop:
- or al, al ; See if negative
- js SGR_Ignore ; Negative, ignore it
-
- cmp al, 7 ; Highest value we have code for
- jg SGR_Ignore ; Can't handle it
-
- cbw ; Blow up to full word
- shl ax, 1 ; Double offset for words
- mov bx, ax ; Copy to bx
- jmp SGR_Table[bx] ; Dispatch thru table to correct routine
-
- SGR_0: mov al, NOT (Blinking + Bold + Inverted + Underscored)
- ; These renditions ...
- and Rendition, al ; Turn off those bits ...
- jmp SHORT SGR_Ignore ; Done with this part
-
- SGR_1: mov al, Bold ; Flag for bold
- jmp SHORT SGR_Set ; Go set the bit
-
- SGR_4: mov al, Underscored ; Flag for underscored
- jmp SHORT SGR_Set ; Go set the bit
-
- SGR_5: mov al, Blinking ; Flag for blinking
- jmp SHORT SGR_Set ; Go set the bit
-
- SGR_7: mov al, Inverted ; Flag for inverted
-
- SGR_Set: or Rendition, al ; Set the bit
-
- SGR_Ignore:
- call Get_next_number ; Try to get another number
- jmp SHORT SGR_Done ; No such luck ...
- nop ; 3 bytes
-
- jmp SGR_Loop ; Got one, go do something with it
-
- SGR_Done:
- call Set_attribute_byte ; Set attr based on rendition
- jmp Done_with_char ; Done with this one
-
-
- ; Set Mode
-
- PUBLIC SM
-
- SM: call Default_zero ; Get the first parameter, default is 0
-
- SM_1: cmp al, 1 ; One?
- jne SM_2 ; No
-
- or VT100_status_flags, Cursor_keys_mode ; Turn on the bit
-
- SM_2: call Get_next_number ; Try to get another number
- jmp Done_with_char
-
- jmp SM_1 ; Got one, go do something with it
-
- VT100_Routines ENDP
-
- Code ENDS
-
- END
-